UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

191 lines 34.2 kB
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=