@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
191 lines • 34.2 kB
JavaScript
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, HostBinding, inject, Input, Output, Renderer2 } from '@angular/core';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
import { ResizableTableType } from './resizable-table-base.service';
import { RESIZABLE_TABLE_SERVICE_TOKEN } from './resizable-table-service.token';
import { ColumnUnit } from './table-column-resize-standard/resizable-table.service';
import * as i0 from "@angular/core";
import * as i1 from "../../../directives/accessibility/focus-indicator/focus-indicator.directive";
import * as i2 from "../../../directives/drag/drag.directive";
export class ResizableTableColumnComponent {
constructor() {
this._table = inject(RESIZABLE_TABLE_SERVICE_TOKEN);
this._elementRef = inject(ElementRef);
this._renderer = inject(Renderer2);
/** Show/Hide column resizable handle */
this._handleVisible = true;
/** Disabled the column resizing */
this.disabled = false;
/** Emit the current column width */
this.widthChange = new EventEmitter();
/** Determine if this column is a variable width column */
this.isFixedWidth = false;
/** Emit when all observables should be unsubscribed */
this._onDestroy = new Subject();
}
get handleVisible() {
return this._handleVisible;
}
set handleVisible(value) {
this._handleVisible = coerceBooleanProperty(value);
}
/** Define the width of a column */
set width(width) {
// there may be cases where columns are created with an `*ngFor` and a width
// may be specified on *some* columns and not others. This this setter will
// still be called whenever the value is empty and this will mark this column
// as having a fixed width, even though it doesn't. So we should only proceed
// whenever there is an actual numeric value passed in.
if (width === null || width === undefined) {
return;
}
// ensure width is a valid number
this._width = coerceNumberProperty(width);
// note that this column has a fixed width
this.isFixedWidth = true;
// if we have not initialised then set the element width
if (!this._table.isInitialised$.value) {
this._renderer.setStyle(this._elementRef.nativeElement, 'width', `${this._width}px`);
}
else {
// if it is initialised then resize the column
const currentWidth = this._table.getColumnWidth(this.getCellIndex(), ColumnUnit.Pixel);
// resize the column by the difference in size
if (isNaN(currentWidth)) {
this._table.resizeColumn(this.getCellIndex(), this._width, false);
}
else {
this._table.resizeColumn(this.getCellIndex(), this._width - currentWidth, false);
}
}
}
get width() {
return this._width;
}
/** Get the minimum width allowed by the column */
get minWidth() {
// determine the minimum width of the column based on its computed CSS value
const computed = parseFloat(getComputedStyle(this._elementRef.nativeElement).minWidth);
// if it is disabled use its current width - otherwise use its CSS min width if it is valid
return this.disabled ? this._elementRef.nativeElement.offsetWidth : isNaN(computed) ? 0 : computed;
}
ngAfterViewInit() {
// initially emit the size when we have initialised
this._table.isInitialised$.pipe(takeUntil(this._onDestroy), filter(isInitialised => isInitialised))
.subscribe(() => {
// get the current min-width
this._minWidth = parseFloat(getComputedStyle(this._elementRef.nativeElement).minWidth);
const width = this._table.getColumnWidth(this.getCellIndex(), ColumnUnit.Pixel);
if (!isNaN(width)) {
this.widthChange.emit(width);
}
});
// ensure the correct width gets emitted on column size change
this._table.onResize$.pipe(takeUntil(this._onDestroy)).subscribe(() => {
this.setColumnWidth();
this.setColumnFlex();
// get the current table width
const width = this._table.getColumnWidth(this.getCellIndex(), ColumnUnit.Pixel);
// check if the width actually changed - otherwise don't emit
if (!isNaN(width) && (this._width === undefined || Math.max(width, this._width) - Math.min(width, this._width) >= 1)) {
this.widthChange.emit(width);
}
});
}
/** Cleanup when component is destroyed */
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
/** Get the natural pixel width of the column */
getNaturalWidth() {
return this._width || this._elementRef.nativeElement.offsetWidth;
}
/** When the dragging starts */
onDragStart(event) {
// determine the mouse position within the handle
this._offset = event.clientX - event.target.getBoundingClientRect().left;
}
/** When the mouse is moved */
onDragMove(event, handle) {
// get the current mouse position
const mouseX = event.pageX - pageXOffset;
// position of the drag handle
const { left } = handle.getBoundingClientRect();
// determine how much the mouse has moved since the last update
const delta = mouseX - (left + this._offset);
// perform resizing
this._table.resizeColumn(this.getCellIndex(), delta);
// set the resizing state
this._table.setResizing(true);
}
/** When the dragging ends */
onDragEnd() {
this._table.setResizing(false);
}
/** Shrink the column when the left arrow key is pressed */
onMoveLeft() {
this._table.resizeColumn(this.getCellIndex(), -10);
}
/** Grow the column when the right arrow key is pressed */
onMoveRight() {
this._table.resizeColumn(this.getCellIndex(), 10);
}
/** Get the column index this cell is part of */
getCellIndex() {
return this._elementRef.nativeElement.cellIndex;
}
/** The percentage width of the column */
setColumnWidth() {
if (this.disabled && this._width !== undefined) {
this._renderer.setStyle(this._elementRef.nativeElement, 'width', `${this._width}px`);
this._renderer.setStyle(this._elementRef.nativeElement, 'max-width', `${this._width}px`);
return;
}
if (!this._table.isInitialised$.value) {
return;
}
const width = this._table.isResizing$.value ?
`${this._table.getColumnWidth(this.getCellIndex(), ColumnUnit.Pixel)}px` :
`${this._table.getColumnWidth(this.getCellIndex(), ColumnUnit.Percentage)}%`;
this._renderer.setStyle(this._elementRef.nativeElement, 'width', width);
this._renderer.setStyle(this._elementRef.nativeElement, 'max-width', null);
}
/** The flex width of the column */
setColumnFlex() {
let flex;
// if we are resizing then always return 'none' to allow free movement
if (this._table.isResizing$.value || this.disabled) {
this._renderer.setStyle(this._elementRef.nativeElement, 'flex', 'none');
}
if (this._table.type === ResizableTableType.Expand) {
flex = this._table.isInitialised$.value ? `0 0 ${this._table.getColumnWidth(this.getCellIndex(), ColumnUnit.Pixel)}px` : '';
}
else {
flex = this._table.isInitialised$.value ? `0 1 ${this._table.getColumnWidth(this.getCellIndex(), ColumnUnit.Percentage)}%` : '';
}
this._renderer.setStyle(this._elementRef.nativeElement, 'flex', flex);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ResizableTableColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: ResizableTableColumnComponent, selector: "[uxResizableTableColumn]", inputs: { disabled: "disabled", handleVisible: "handleVisible", width: "width" }, outputs: { widthChange: "widthChange" }, host: { properties: { "class.ux-resizable-table-hide-handle": "!handleVisible", "class.ux-resizable-table-column-disabled": "this.disabled" }, classAttribute: "ux-resizable-table-column" }, ngImport: i0, template: "<div class=\"ux-resizable-table-column-content\">\n <ng-content></ng-content>\n</div>\n\n<div class=\"ux-resizable-table-column-actions\">\n <ng-content select=\"ux-column-sorting\"></ng-content>\n</div>\n\n@if (!disabled && handleVisible) {\n <div #handle\n uxDrag\n uxFocusIndicator\n tabindex=\"0\"\n role=\"separator\"\n aria-label=\"Column resize handle. Use arrow keys to change the column width.\"\n class=\"ux-resizable-table-column-handle\"\n [attr.aria-valuemin]=\"minWidth\"\n [attr.aria-valuenow]=\"width\"\n (onDragStart)=\"onDragStart($event)\"\n (onDrag)=\"onDragMove($event, handle)\"\n (onDragEnd)=\"onDragEnd()\"\n (keydown.ArrowLeft)=\"onMoveLeft()\"\n (keydown.ArrowRight)=\"onMoveRight()\"\n (click)=\"$event.stopPropagation()\">\n <div class=\"ux-resizable-table-column-handle-icon\"></div>\n </div>\n}\n\n", dependencies: [{ kind: "directive", type: i1.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "directive", type: i2.DragDirective, selector: "[uxDrag]", inputs: ["clone", "group", "model", "draggable"], outputs: ["onDragStart", "onDrag", "onDragScroll", "onDragEnd", "onDrop", "onDropEnter", "onDropLeave"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ResizableTableColumnComponent, decorators: [{
type: Component,
args: [{ selector: '[uxResizableTableColumn]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
class: 'ux-resizable-table-column',
'[class.ux-resizable-table-hide-handle]': '!handleVisible'
}, template: "<div class=\"ux-resizable-table-column-content\">\n <ng-content></ng-content>\n</div>\n\n<div class=\"ux-resizable-table-column-actions\">\n <ng-content select=\"ux-column-sorting\"></ng-content>\n</div>\n\n@if (!disabled && handleVisible) {\n <div #handle\n uxDrag\n uxFocusIndicator\n tabindex=\"0\"\n role=\"separator\"\n aria-label=\"Column resize handle. Use arrow keys to change the column width.\"\n class=\"ux-resizable-table-column-handle\"\n [attr.aria-valuemin]=\"minWidth\"\n [attr.aria-valuenow]=\"width\"\n (onDragStart)=\"onDragStart($event)\"\n (onDrag)=\"onDragMove($event, handle)\"\n (onDragEnd)=\"onDragEnd()\"\n (keydown.ArrowLeft)=\"onMoveLeft()\"\n (keydown.ArrowRight)=\"onMoveRight()\"\n (click)=\"$event.stopPropagation()\">\n <div class=\"ux-resizable-table-column-handle-icon\"></div>\n </div>\n}\n\n" }]
}], propDecorators: { disabled: [{
type: Input
}, {
type: HostBinding,
args: ['class.ux-resizable-table-column-disabled']
}], handleVisible: [{
type: Input
}], width: [{
type: Input
}], widthChange: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXphYmxlLXRhYmxlLWNvbHVtbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy90YWJsZS90YWJsZS1jb2x1bW4tcmVzaXplL3Jlc2l6YWJsZS10YWJsZS1jb2x1bW4uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdGFibGUvdGFibGUtY29sdW1uLXJlc2l6ZS9yZXNpemFibGUtdGFibGUtY29sdW1uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BGLE9BQU8sRUFBaUIsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQWEsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0SyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEUsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDaEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdEQUF3RCxDQUFDOzs7O0FBV3BGLE1BQU0sT0FBTyw2QkFBNkI7SUFUMUM7UUFVcUIsV0FBTSxHQUFHLE1BQU0sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBRS9DLGdCQUFXLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRWpDLGNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFL0Msd0NBQXdDO1FBQ2hDLG1CQUFjLEdBQVks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QyxjQUFjLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFLFVBQVUsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDcEksQ0FBQztRQUVELElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUMxRSxDQUFDOytHQXhOUSw2QkFBNkI7bUdBQTdCLDZCQUE2Qix5WENqQjFDLCsyQkE0QkE7OzRGRFhhLDZCQUE2QjtrQkFUekMsU0FBUzsrQkFDSSwwQkFBMEIsbUJBRW5CLHVCQUF1QixDQUFDLE1BQU0sUUFDekM7d0JBQ0YsS0FBSyxFQUFFLDJCQUEyQjt3QkFDbEMsd0NBQXdDLEVBQUUsZ0JBQWdCO3FCQUM3RDs4QkFlRCxRQUFRO3NCQUZQLEtBQUs7O3NCQUNMLFdBQVc7dUJBQUMsMENBQTBDO2dCQUluRCxhQUFhO3NCQURoQixLQUFLO2dCQVVPLEtBQUs7c0JBQWpCLEtBQUs7Z0JBeUNJLFdBQVc7c0JBQXBCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb2VyY2VCb29sZWFuUHJvcGVydHksIGNvZXJjZU51bWJlclByb3BlcnR5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcbmltcG9ydCB7IEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSG9zdEJpbmRpbmcsIGluamVjdCwgSW5wdXQsIE9uRGVzdHJveSwgT3V0cHV0LCBSZW5kZXJlcjIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGZpbHRlciwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgUmVzaXphYmxlVGFibGVUeXBlIH0gZnJvbSAnLi9yZXNpemFibGUtdGFibGUtYmFzZS5zZXJ2aWNlJztcbmltcG9ydCB7IFJFU0laQUJMRV9UQUJMRV9TRVJWSUNFX1RPS0VOIH0gZnJvbSAnLi9yZXNpemFibGUtdGFibGUtc2VydmljZS50b2tlbic7XG5pbXBvcnQgeyBDb2x1bW5Vbml0IH0gZnJvbSAnLi90YWJsZS1jb2x1bW4tcmVzaXplLXN0YW5kYXJkL3Jlc2l6YWJsZS10YWJsZS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdbdXhSZXNpemFibGVUYWJsZUNvbHVtbl0nLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9yZXNpemFibGUtdGFibGUtY29sdW1uLmNvbXBvbmVudC5odG1sJyxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgICBob3N0OiB7XG4gICAgICAgIGNsYXNzOiAndXgtcmVzaXphYmxlLXRhYmxlLWNvbHVtbicsXG4gICAgICAgICdbY2xhc3MudXgtcmVzaXphYmxlLXRhYmxlLWhpZGUtaGFuZGxlXSc6ICchaGFuZGxlVmlzaWJsZSdcbiAgICB9XG59KVxuZXhwb3J0IGNsYXNzIFJlc2l6YWJsZVRhYmxlQ29sdW1uQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF90YWJsZSA9IGluamVjdChSRVNJWkFCTEVfVEFCTEVfU0VSVklDRV9UT0tFTik7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9lbGVtZW50UmVmID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBfcmVuZGVyZXIgPSBpbmplY3QoUmVuZGVyZXIyKTtcblxuICAgIC8qKiBTaG93L0hpZGUgY29sdW1uIHJlc2l6YWJsZSBoYW5kbGUgKi9cbiAgICBwcml2YXRlIF9oYW5kbGVWaXNpYmxlOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKiBEaXNhYmxlZCB0aGUgY29sdW1uIHJlc2l6aW5nICovXG4gICAgQElucHV0KClcbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLnV4LXJlc2l6YWJsZS10YWJsZS1jb2x1bW4tZGlzYWJsZWQnKVxuICAgIGRpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBASW5wdXQoKVxuICAgIGdldCBoYW5kbGVWaXNpYmxlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faGFuZGxlVmlzaWJsZTtcbiAgICB9XG5cbiAgICBzZXQgaGFuZGxlVmlzaWJsZSh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9oYW5kbGVWaXNpYmxlID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKiogRGVmaW5lIHRoZSB3aWR0aCBvZiBhIGNvbHVtbiAqL1xuICAgIEBJbnB1dCgpIHNldCB3aWR0aCh3aWR0aDogbnVtYmVyKSB7XG5cbiAgICAgICAgLy8gdGhlcmUgbWF5IGJlIGNhc2VzIHdoZXJlIGNvbHVtbnMgYXJlIGNyZWF0ZWQgd2l0aCBhbiBgKm5nRm9yYCBhbmQgYSB3aWR0aFxuICAgICAgICAvLyBtYXkgYmUgc3BlY2lmaWVkIG9uICpzb21lKiBjb2x1bW5zIGFuZCBub3Qgb3RoZXJzLiBUaGlzIHRoaXMgc2V0dGVyIHdpbGxcbiAgICAgICAgLy8gc3RpbGwgYmUgY2FsbGVkIHdoZW5ldmVyIHRoZSB2YWx1ZSBpcyBlbXB0eSBhbmQgdGhpcyB3aWxsIG1hcmsgdGhpcyBjb2x1bW5cbiAgICAgICAgLy8gYXMgaGF2aW5nIGEgZml4ZWQgd2lkdGgsIGV2ZW4gdGhvdWdoIGl0IGRvZXNuJ3QuIFNvIHdlIHNob3VsZCBvbmx5IHByb2NlZWRcbiAgICAgICAgLy8gd2hlbmV2ZXIgdGhlcmUgaXMgYW4gYWN0dWFsIG51bWVyaWMgdmFsdWUgcGFzc2VkIGluLlxuICAgICAgICBpZiAod2lkdGggPT09IG51bGwgfHwgd2lkdGggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZW5zdXJlIHdpZHRoIGlzIGEgdmFsaWQgbnVtYmVyXG4gICAgICAgIHRoaXMuX3dpZHRoID0gY29lcmNlTnVtYmVyUHJvcGVydHkod2lkdGgpO1xuXG4gICAgICAgIC8vIG5vdGUgdGhhdCB0aGlzIGNvbHVtbiBoYXMgYSBmaXhlZCB3aWR0aFxuICAgICAgICB0aGlzLmlzRml4ZWRXaWR0aCA9IHRydWU7XG5cbiAgICAgICAgLy8gaWYgd2UgaGF2ZSBub3QgaW5pdGlhbGlzZWQgdGhlbiBzZXQgdGhlIGVsZW1lbnQgd2lkdGhcbiAgICAgICAgaWYgKCF0aGlzLl90YWJsZS5pc0luaXRpYWxpc2VkJC52YWx1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICd3aWR0aCcsIGAke3RoaXMuX3dpZHRofXB4YCk7XG5cbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgLy8gaWYgaXQgaXMgaW5pdGlhbGlzZWQgdGhlbiByZXNpemUgdGhlIGNvbHVtblxuICAgICAgICAgICAgY29uc3QgY3VycmVudFdpZHRoID0gdGhpcy5fdGFibGUuZ2V0Q29sdW1uV2lkdGgodGhpcy5nZXRDZWxsSW5kZXgoKSwgQ29sdW1uVW5pdC5QaXhlbCk7XG5cbiAgICAgICAgICAgIC8vIHJlc2l6ZSB0aGUgY29sdW1uIGJ5IHRoZSBkaWZmZXJlbmNlIGluIHNpemVcbiAgICAgICAgICAgIGlmIChpc05hTihjdXJyZW50V2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdGFibGUucmVzaXplQ29sdW1uKHRoaXMuZ2V0Q2VsbEluZGV4KCksIHRoaXMuX3dpZHRoLCBmYWxzZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3RhYmxlLnJlc2l6ZUNvbHVtbih0aGlzLmdldENlbGxJbmRleCgpLCB0aGlzLl93aWR0aCAtIGN1cnJlbnRXaWR0aCwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0IHdpZHRoKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl93aWR0aDtcbiAgICB9XG5cbiAgICAvKiogRW1pdCB0aGUgY3VycmVudCBjb2x1bW4gd2lkdGggKi9cbiAgICBAT3V0cHV0KCkgd2lkdGhDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcblxuICAgIC8qKiBHZXQgdGhlIG1pbmltdW0gd2lkdGggYWxsb3dlZCBieSB0aGUgY29sdW1uICovXG4gICAgZ2V0IG1pbldpZHRoKCk6IG51bWJlciB7XG4gICAgICAgIC8vIGRldGVybWluZSB0aGUgbWluaW11bSB3aWR0aCBvZiB0aGUgY29sdW1uIGJhc2VkIG9uIGl0cyBjb21wdXRlZCBDU1MgdmFsdWVcbiAgICAgICAgY29uc3QgY29tcHV0ZWQgPSBwYXJzZUZsb2F0KGdldENvbXB1dGVkU3R5bGUodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KS5taW5XaWR0aCk7XG5cbiAgICAgICAgLy8gaWYgaXQgaXMgZGlzYWJsZWQgdXNlIGl0cyBjdXJyZW50IHdpZHRoIC0gb3RoZXJ3aXNlIHVzZSBpdHMgQ1NTIG1pbiB3aWR0aCBpZiBpdCBpcyB2YWxpZFxuICAgICAgICByZXR1cm4gdGhpcy5kaXNhYmxlZCA/IHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aCA6IGlzTmFOKGNvbXB1dGVkKSA/IDAgOiBjb21wdXRlZDtcbiAgICB9XG5cbiAgICAvKiogRGV0ZXJtaW5lIGlmIHRoaXMgY29sdW1uIGlzIGEgdmFyaWFibGUgd2lkdGggY29sdW1uICovXG4gICAgaXNGaXhlZFdpZHRoOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogU3RvcmUgdGhlIHdpZHRoIHNwZWNpZmljYWxseSBzZXQgYnkgdGhlIGlucHV0ICovXG4gICAgcHJpdmF0ZSBfd2lkdGg6IG51bWJlcjtcblxuICAgIC8qKiBTdG9yZSB0aGUgcG9zaXRpb24gb2YgdGhlIG1vdXNlIHdpdGhpbiB0aGUgZHJhZyBoYW5kbGUgKi9cbiAgICBwcml2YXRlIF9vZmZzZXQ6IG51bWJlcjtcblxuICAgIC8qKiBNaW4gd2lkdGggb2YgdGhlIGNvbHVtbiovXG4gICAgcHJpdmF0ZSBfbWluV2lkdGg6IG51bWJlcjtcblxuICAgIC8qKiBFbWl0IHdoZW4gYWxsIG9ic2VydmFibGVzIHNob3VsZCBiZSB1bnN1YnNjcmliZWQgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9vbkRlc3Ryb3kgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICAvLyBpbml0aWFsbHkgZW1pdCB0aGUgc2l6ZSB3aGVuIHdlIGhhdmUgaW5pdGlhbGlzZWRcbiAgICAgICAgdGhpcy5fdGFibGUuaXNJbml0aWFsaXNlZCQucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSwgZmlsdGVyKGlzSW5pdGlhbGlzZWQgPT4gaXNJbml0aWFsaXNlZCkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBnZXQgdGhlIGN1cnJlbnQgbWluLXdpZHRoXG4gICAgICAgICAgICAgICAgdGhpcy5fbWluV2lkdGggPSBwYXJzZUZsb2F0KGdldENvbXB1dGVkU3R5bGUodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KS5taW5XaWR0aCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuX3RhYmxlLmdldENvbHVtbldpZHRoKHRoaXMuZ2V0Q2VsbEluZGV4KCksIENvbHVtblVuaXQuUGl4ZWwpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTih3aWR0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWR0aENoYW5nZS5lbWl0KHdpZHRoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBlbnN1cmUgdGhlIGNvcnJlY3Qgd2lkdGggZ2V0cyBlbWl0dGVkIG9uIGNvbHVtbiBzaXplIGNoYW5nZVxuICAgICAgICB0aGlzLl90YWJsZS5vblJlc2l6ZSQucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0Q29sdW1uV2lkdGgoKTtcbiAgICAgICAgICAgIHRoaXMuc2V0Q29sdW1uRmxleCgpO1xuXG4gICAgICAgICAgICAvLyBnZXQgdGhlIGN1cnJlbnQgdGFibGUgd2lkdGhcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5fdGFibGUuZ2V0Q29sdW1uV2lkdGgodGhpcy5nZXRDZWxsSW5kZXgoKSwgQ29sdW1uVW5pdC5QaXhlbCk7XG5cbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHRoZSB3aWR0aCBhY3R1YWxseSBjaGFuZ2VkIC0gb3RoZXJ3aXNlIGRvbid0IGVtaXRcbiAgICAgICAgICAgIGlmICghaXNOYU4od2lkdGgpICYmICh0aGlzLl93aWR0aCA9PT0gdW5kZWZpbmVkIHx8IE1hdGgubWF4KHdpZHRoLCB0aGlzLl93aWR0aCkgLSBNYXRoLm1pbih3aWR0aCwgdGhpcy5fd2lkdGgpID49IDEpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53aWR0aENoYW5nZS5lbWl0KHdpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIENsZWFudXAgd2hlbiBjb21wb25lbnQgaXMgZGVzdHJveWVkICovXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5uZXh0KCk7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIC8qKiBHZXQgdGhlIG5hdHVyYWwgcGl4ZWwgd2lkdGggb2YgdGhlIGNvbHVtbiAqL1xuICAgIGdldE5hdHVyYWxXaWR0aCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fd2lkdGggfHwgdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoO1xuICAgIH1cblxuICAgIC8qKiBXaGVuIHRoZSBkcmFnZ2luZyBzdGFydHMgKi9cbiAgICBvbkRyYWdTdGFydChldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgICAgICAvLyBkZXRlcm1pbmUgdGhlIG1vdXNlIHBvc2l0aW9uIHdpdGhpbiB0aGUgaGFuZGxlXG4gICAgICAgIHRoaXMuX29mZnNldCA9IGV2ZW50LmNsaWVudFggLSAoZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50KS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuICAgIH1cblxuICAgIC8qKiBXaGVuIHRoZSBtb3VzZSBpcyBtb3ZlZCAqL1xuICAgIG9uRHJhZ01vdmUoZXZlbnQ6IE1vdXNlRXZlbnQsIGhhbmRsZTogSFRNTERpdkVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBnZXQgdGhlIGN1cnJlbnQgbW91c2UgcG9zaXRpb25cbiAgICAgICAgY29uc3QgbW91c2VYID0gZXZlbnQucGFnZVggLSBwYWdlWE9mZnNldDtcblxuICAgICAgICAvLyBwb3NpdGlvbiBvZiB0aGUgZHJhZyBoYW5kbGVcbiAgICAgICAgY29uc3QgeyBsZWZ0IH0gPSBoYW5kbGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgLy8gZGV0ZXJtaW5lIGhvdyBtdWNoIHRoZSBtb3VzZSBoYXMgbW92ZWQgc2luY2UgdGhlIGxhc3QgdXBkYXRlXG4gICAgICAgIGNvbnN0IGRlbHRhID0gbW91c2VYIC0gKGxlZnQgKyB0aGlzLl9vZmZzZXQpO1xuXG4gICAgICAgIC8vIHBlcmZvcm0gcmVzaXppbmdcbiAgICAgICAgdGhpcy5fdGFibGUucmVzaXplQ29sdW1uKHRoaXMuZ2V0Q2VsbEluZGV4KCksIGRlbHRhKTtcblxuICAgICAgICAvLyBzZXQgdGhlIHJlc2l6aW5nIHN0YXRlXG4gICAgICAgIHRoaXMuX3RhYmxlLnNldFJlc2l6aW5nKHRydWUpO1xuICAgIH1cblxuICAgIC8qKiBXaGVuIHRoZSBkcmFnZ2luZyBlbmRzICovXG4gICAgb25EcmFnRW5kKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl90YWJsZS5zZXRSZXNpemluZyhmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqIFNocmluayB0aGUgY29sdW1uIHdoZW4gdGhlIGxlZnQgYXJyb3cga2V5IGlzIHByZXNzZWQgKi9cbiAgICBvbk1vdmVMZWZ0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl90YWJsZS5yZXNpemVDb2x1bW4odGhpcy5nZXRDZWxsSW5kZXgoKSwgLTEwKTtcbiAgICB9XG5cbiAgICAvKiogR3JvdyB0aGUgY29sdW1uIHdoZW4gdGhlIHJpZ2h0IGFycm93IGtleSBpcyBwcmVzc2VkICovXG4gICAgb25Nb3ZlUmlnaHQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX3RhYmxlLnJlc2l6ZUNvbHVtbih0aGlzLmdldENlbGxJbmRleCgpLCAxMCk7XG4gICAgfVxuXG4gICAgLyoqIEdldCB0aGUgY29sdW1uIGluZGV4IHRoaXMgY2VsbCBpcyBwYXJ0IG9mICovXG4gICAgZ2V0Q2VsbEluZGV4KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiAodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxUYWJsZUNlbGxFbGVtZW50KS5jZWxsSW5kZXg7XG4gICAgfVxuXG4gICAgLyoqIFRoZSBwZXJjZW50YWdlIHdpZHRoIG9mIHRoZSBjb2x1bW4gKi9cbiAgICBwcml2YXRlIHNldENvbHVtbldpZHRoKCk6IHZvaWQge1xuXG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVkICYmIHRoaXMuX3dpZHRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3dpZHRoJywgYCR7dGhpcy5fd2lkdGh9cHhgKTtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ21heC13aWR0aCcsIGAke3RoaXMuX3dpZHRofXB4YCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuX3RhYmxlLmlzSW5pdGlhbGlzZWQkLnZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuX3RhYmxlLmlzUmVzaXppbmckLnZhbHVlID9cbiAgICAgICAgICAgIGAke3RoaXMuX3RhYmxlLmdldENvbHVtbldpZHRoKHRoaXMuZ2V0Q2VsbEluZGV4KCksIENvbHVtblVuaXQuUGl4ZWwpfXB4YCA6XG4gICAgICAgICAgICBgJHt0aGlzLl90YWJsZS5nZXRDb2x1bW5XaWR0aCh0aGlzLmdldENlbGxJbmRleCgpLCBDb2x1bW5Vbml0LlBlcmNlbnRhZ2UpfSVgO1xuXG5cbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnd2lkdGgnLCB3aWR0aCk7XG4gICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ21heC13aWR0aCcsIG51bGwpO1xuICAgIH1cblxuICAgIC8qKiBUaGUgZmxleCB3aWR0aCBvZiB0aGUgY29sdW1uICovXG4gICAgcHJpdmF0ZSBzZXRDb2x1bW5GbGV4KCk6IHZvaWQge1xuXG4gICAgICAgIGxldCBmbGV4O1xuXG4gICAgICAgIC8vIGlmIHdlIGFyZSByZXNpemluZyB0aGVuIGFsd2F5cyByZXR1cm4gJ25vbmUnIHRvIGFsbG93IGZyZWUgbW92ZW1lbnRcbiAgICAgICAgaWYgKHRoaXMuX3RhYmxlLmlzUmVzaXppbmckLnZhbHVlIHx8IHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ2ZsZXgnLCAnbm9uZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX3RhYmxlLnR5cGUgPT09IFJlc2l6YWJsZVRhYmxlVHlwZS5FeHBhbmQpIHtcbiAgICAgICAgICAgIGZsZXggPSB0aGlzLl90YWJsZS5pc0luaXRpYWxpc2VkJC52YWx1ZSA/IGAwIDAgJHt0aGlzLl90YWJsZS5nZXRDb2x1bW5XaWR0aCh0aGlzLmdldENlbGxJbmRleCgpLCBDb2x1bW5Vbml0LlBpeGVsKX1weGAgOiAnJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZsZXggPSB0aGlzLl90YWJsZS5pc0luaXRpYWxpc2VkJC52YWx1ZSA/IGAwIDEgJHt0aGlzLl90YWJsZS5nZXRDb2x1bW5XaWR0aCh0aGlzLmdldENlbGxJbmRleCgpLCBDb2x1bW5Vbml0LlBlcmNlbnRhZ2UpfSVgIDogJyc7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdmbGV4JywgZmxleCk7XG4gICAgfVxufSIsIjxkaXYgY2xhc3M9XCJ1eC1yZXNpemFibGUtdGFibGUtY29sdW1uLWNvbnRlbnRcIj5cbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9kaXY+XG5cbjxkaXYgY2xhc3M9XCJ1eC1yZXNpemFibGUtdGFibGUtY29sdW1uLWFjdGlvbnNcIj5cbiAgPG5nLWNvbnRlbnQgc2VsZWN0PVwidXgtY29sdW1uLXNvcnRpbmdcIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cblxuQGlmICghZGlzYWJsZWQgJiYgaGFuZGxlVmlzaWJsZSkge1xuICA8ZGl2ICNoYW5kbGVcbiAgICB1eERyYWdcbiAgICB1eEZvY3VzSW5kaWNhdG9yXG4gICAgdGFiaW5kZXg9XCIwXCJcbiAgICByb2xlPVwic2VwYXJhdG9yXCJcbiAgICBhcmlhLWxhYmVsPVwiQ29sdW1uIHJlc2l6ZSBoYW5kbGUuIFVzZSBhcnJvdyBrZXlzIHRvIGNoYW5nZSB0aGUgY29sdW1uIHdpZHRoLlwiXG4gICAgY2xhc3M9XCJ1eC1yZXNpemFibGUtdGFibGUtY29sdW1uLWhhbmRsZVwiXG4gICAgW2F0dHIuYXJpYS12YWx1ZW1pbl09XCJtaW5XaWR0aFwiXG4gICAgW2F0dHIuYXJpYS12YWx1ZW5vd109XCJ3aWR0aFwiXG4gICAgKG9uRHJhZ1N0YXJ0KT1cIm9uRHJhZ1N0YXJ0KCRldmVudClcIlxuICAgIChvbkRyYWcpPVwib25EcmFnTW92ZSgkZXZlbnQsIGhhbmRsZSlcIlxuICAgIChvbkRyYWdFbmQpPVwib25EcmFnRW5kKClcIlxuICAgIChrZXlkb3duLkFycm93TGVmdCk9XCJvbk1vdmVMZWZ0KClcIlxuICAgIChrZXlkb3duLkFycm93UmlnaHQpPVwib25Nb3ZlUmlnaHQoKVwiXG4gICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiPlxuICAgIDxkaXYgY2xhc3M9XCJ1eC1yZXNpemFibGUtdGFibGUtY29sdW1uLWhhbmRsZS1pY29uXCI+PC9kaXY+XG4gIDwvZGl2PlxufVxuXG4iXX0=