UNPKG

fundamental-ngx

Version:

SAP Fundamentals, implemented in Angular

450 lines 31.9 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, ElementRef, EventEmitter, forwardRef, Input, Output, QueryList, TemplateRef, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { MenuItemDirective } from '../menu/menu-item.directive'; import { MenuKeyboardService } from '../menu/menu-keyboard.service'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; /** * Allows users to filter through results and select a value. * * Supports Angular Forms. */ export class ComboboxComponent { /** * @param {?} menuKeyboardService */ constructor(menuKeyboardService) { this.menuKeyboardService = menuKeyboardService; /** * Values to be filtered in the search input. */ this.dropdownValues = []; /** * Filter function. Accepts an array of objects and a search term as arguments * and returns a string. See search input examples for details. */ this.filterFn = this.defaultFilter; /** * Icon to display in the right-side button. */ this.glyph = 'navigation-down-arrow'; /** * Max height of the popover. Any overflowing elements will be accessible through scrolling. */ this.maxHeight = '200px'; /** * Whether the search input should be displayed in compact mode. */ this.compact = false; /** * Whether the matching string should be highlighted during filtration. */ this.highlighting = true; /** * Whether the popover should close when a user selects a result. */ this.closeOnSelect = true; /** * Whether the input field should be populated with the result picked by the user. */ this.fillOnSelect = true; /** * Display function. Accepts an object of the same type as the * items passed to dropdownValues as argument, and outputs a string. * An arrow function can be used to access the *this* keyword in the calling component. * See search input examples for details. */ this.displayFn = this.defaultDisplay; /** * Event emitted when an item is clicked. Use *$event* to retrieve it. */ this.itemClicked = new EventEmitter(); /** * @hidden */ this.displayedValues = []; /** * @hidden */ this.isOpen = false; /** * @hidden */ this.onDestroy$ = new Subject(); /** * @hidden */ this.onChange = (/** * @return {?} */ () => { }); /** * @hidden */ this.onTouched = (/** * @return {?} */ () => { }); } /** * @hidden * @return {?} */ ngOnInit() { if (this.dropdownValues) { this.displayedValues = this.dropdownValues; } } /** * @hidden * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (this.dropdownValues && (changes.dropdownValues || changes.searchTerm)) { if (this.inputText) { this.displayedValues = this.filterFn(this.dropdownValues, this.inputText); } else { this.displayedValues = this.dropdownValues; } } } /** * @return {?} */ ngOnDestroy() { this.onDestroy$.next(); this.onDestroy$.complete(); } /** * @hidden * @return {?} */ ngAfterViewInit() { this.menuKeyboardService.itemClicked .pipe(takeUntil(this.onDestroy$)) .subscribe((/** * @param {?} index * @return {?} */ index => this.onMenuClickHandler(index))); this.menuKeyboardService.focusEscapeBeforeList = (/** * @return {?} */ () => this.searchInputElement.nativeElement.focus()); this.menuKeyboardService.focusEscapeAfterList = (/** * @return {?} */ () => { }); } /** * @hidden * @param {?} event * @return {?} */ onInputKeydownHandler(event) { if (event.code === 'Enter' && this.searchFunction) { this.searchFunction(); } else if (event.code === 'ArrowDown') { event.preventDefault(); if (this.menuItems && this.menuItems.first) { this.menuItems.first.focus(); } } } /** * @hidden * @return {?} */ onInputKeyupHandler() { if (this.inputText && this.inputText.length) { this.isOpen = true; } } /** * @hidden * @param {?} event * @param {?} index * @return {?} */ onMenuKeydownHandler(event, index) { this.menuKeyboardService.keyDownHandler(event, index, this.menuItems.toArray()); } /** * @hidden * @param {?} index * @return {?} */ onMenuClickHandler(index) { /** @type {?} */ const selectedItem = this.displayedValues[index]; if (selectedItem) { this.handleClickActions(selectedItem); this.itemClicked.emit({ item: selectedItem, index: index }); } } /** * Get the input text of the input. * @return {?} */ get inputText() { return this.inputTextValue; } /** * Set the input text of the input. * @param {?} value * @return {?} */ set inputText(value) { this.inputTextValue = value; this.onChange(value); this.onTouched(); } /** * @hidden * @param {?} value * @return {?} */ writeValue(value) { this.inputTextValue = value; } /** * @hidden * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = fn; } /** * @hidden * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @hidden * @return {?} */ handleSearchTermChange() { this.displayedValues = this.filterFn(this.dropdownValues, this.inputText); } /** * @private * @param {?} str * @return {?} */ defaultDisplay(str) { return str; } /** * @private * @param {?} contentArray * @param {?} searchTerm * @return {?} */ defaultFilter(contentArray, searchTerm) { /** @type {?} */ const searchLower = searchTerm.toLocaleLowerCase(); return contentArray.filter((/** * @param {?} item * @return {?} */ item => { if (item) { return this.displayFn(item).toLocaleLowerCase().includes(searchLower); } })); } /** * @private * @param {?} term * @return {?} */ handleClickActions(term) { if (this.closeOnSelect) { this.isOpen = false; } if (this.fillOnSelect) { this.inputText = this.displayFn(term); this.handleSearchTermChange(); } } } ComboboxComponent.decorators = [ { type: Component, args: [{ selector: 'fd-combobox', template: "<fd-popover [(isOpen)]=\"isOpen\"\n [fillControlMode]=\"'at-least'\"\n [disabled]=\"disabled\"\n class=\"fd-combobox-popover-custom\"\n [ngClass]=\"{'fd-popover-body--display-none': displayedValues && !displayedValues.length}\">\n <fd-popover-control>\n <div class=\"fd-combobox-control\">\n <div class=\"fd-input-group fd-input-group--after\" [ngClass]=\"{'fd-input-group--compact': compact}\">\n <input #searchInputElement type=\"text\" class=\"fd-input\" [ngClass]=\"{'fd-input--compact': compact}\"\n (keydown)=\"onInputKeydownHandler($event)\"\n (keyup)=\"onInputKeyupHandler()\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"inputText\"\n (ngModelChange)=\"handleSearchTermChange()\"\n placeholder=\"{{placeholder}}\">\n <span class=\"fd-input-group__addon fd-input-group__addon--after fd-input-group__addon--button\">\n <button fd-button\n tabindex=\"-1\"\n type=\"button\"\n [fdType]=\"'light'\"\n [glyph]=\"glyph\"\n [disabled]=\"disabled\">\n </button>\n </span>\n </div>\n </div>\n </fd-popover-control>\n <fd-popover-body *ngIf=\"displayedValues && displayedValues.length\">\n <fd-menu class=\"fd-combobox-input-menu-overflow\"\n [style.maxHeight]=\"maxHeight\">\n <ng-content></ng-content>\n <ul fd-menu-list>\n <li *ngFor=\"let term of displayedValues; let index = index;\"\n (click)=\"onMenuClickHandler(index)\"\n (keydown)=\"onMenuKeydownHandler($event, index)\"\n fd-menu-item\n tabindex=\"0\">\n <span *ngIf=\"!itemTemplate\"\n [innerHTML]=\"term | displayFnPipe:displayFn | highlight:inputText:highlighting\"\n ></span>\n <ng-container *ngIf=\"itemTemplate\">\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: {$implicit: term}\"></ng-container>\n </ng-container>\n </li>\n </ul>\n </fd-menu>\n </fd-popover-body>\n</fd-popover>\n\n", providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ () => ComboboxComponent)), multi: true }, MenuKeyboardService ], host: { '[class.fd-combobox-custom-class]': 'true', '[class.fd-combobox-input]': 'true' }, encapsulation: ViewEncapsulation.None, styles: [".fd-combobox-custom-class,.fd-combobox-custom-class .fd-combobox-popover-custom{display:block}.fd-combobox-custom-class .fd-combobox-input-menu-overflow{overflow:auto}"] }] } ]; /** @nocollapse */ ComboboxComponent.ctorParameters = () => [ { type: MenuKeyboardService } ]; ComboboxComponent.propDecorators = { dropdownValues: [{ type: Input }], filterFn: [{ type: Input }], disabled: [{ type: Input }], placeholder: [{ type: Input }], glyph: [{ type: Input }], itemTemplate: [{ type: Input }], maxHeight: [{ type: Input }], searchFunction: [{ type: Input }], compact: [{ type: Input }], highlighting: [{ type: Input }], closeOnSelect: [{ type: Input }], fillOnSelect: [{ type: Input }], displayFn: [{ type: Input }], itemClicked: [{ type: Output }], menuItems: [{ type: ViewChildren, args: [MenuItemDirective,] }], searchInputElement: [{ type: ViewChild, args: ['searchInputElement',] }] }; if (false) { /** * Values to be filtered in the search input. * @type {?} */ ComboboxComponent.prototype.dropdownValues; /** * Filter function. Accepts an array of objects and a search term as arguments * and returns a string. See search input examples for details. * @type {?} */ ComboboxComponent.prototype.filterFn; /** * Whether the search input is disabled. * * @type {?} */ ComboboxComponent.prototype.disabled; /** * Placeholder of the search input. * * @type {?} */ ComboboxComponent.prototype.placeholder; /** * Icon to display in the right-side button. * @type {?} */ ComboboxComponent.prototype.glyph; /** * The template with which to display the individual listed items. * Use it by passing an ng-template with implicit content. See examples for more info. * @type {?} */ ComboboxComponent.prototype.itemTemplate; /** * Max height of the popover. Any overflowing elements will be accessible through scrolling. * @type {?} */ ComboboxComponent.prototype.maxHeight; /** * Search function to execute when the Enter key is pressed on the main input. * @type {?} */ ComboboxComponent.prototype.searchFunction; /** * Whether the search input should be displayed in compact mode. * @type {?} */ ComboboxComponent.prototype.compact; /** * Whether the matching string should be highlighted during filtration. * @type {?} */ ComboboxComponent.prototype.highlighting; /** * Whether the popover should close when a user selects a result. * @type {?} */ ComboboxComponent.prototype.closeOnSelect; /** * Whether the input field should be populated with the result picked by the user. * @type {?} */ ComboboxComponent.prototype.fillOnSelect; /** * Display function. Accepts an object of the same type as the * items passed to dropdownValues as argument, and outputs a string. * An arrow function can be used to access the *this* keyword in the calling component. * See search input examples for details. * @type {?} */ ComboboxComponent.prototype.displayFn; /** * Event emitted when an item is clicked. Use *$event* to retrieve it. * @type {?} */ ComboboxComponent.prototype.itemClicked; /** * @hidden * @type {?} */ ComboboxComponent.prototype.menuItems; /** * @hidden * @type {?} */ ComboboxComponent.prototype.searchInputElement; /** * @hidden * @type {?} */ ComboboxComponent.prototype.displayedValues; /** * @hidden * @type {?} */ ComboboxComponent.prototype.isOpen; /** * @hidden * @type {?} */ ComboboxComponent.prototype.inputTextValue; /** * @hidden * @type {?} * @private */ ComboboxComponent.prototype.onDestroy$; /** * @hidden * @type {?} */ ComboboxComponent.prototype.onChange; /** * @hidden * @type {?} */ ComboboxComponent.prototype.onTouched; /** * @type {?} * @private */ ComboboxComponent.prototype.menuKeyboardService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tYm9ib3guY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vZnVuZGFtZW50YWwtbmd4LyIsInNvdXJjZXMiOlsibGliL2NvbWJvYm94L2NvbWJvYm94LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUVILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBR0wsTUFBTSxFQUNOLFNBQVMsRUFDTSxXQUFXLEVBQzFCLFNBQVMsRUFDVCxZQUFZLEVBQ1osaUJBQWlCLEVBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7O0FBeUIzQyxNQUFNLE9BQU8saUJBQWlCOzs7O0lBMkYxQixZQUFvQixtQkFBd0M7UUFBeEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjs7OztRQXZGNUQsbUJBQWMsR0FBVSxFQUFFLENBQUM7Ozs7O1FBSzNCLGFBQVEsR0FBYSxJQUFJLENBQUMsYUFBYSxDQUFDOzs7O1FBWXhDLFVBQUssR0FBVyx1QkFBdUIsQ0FBQzs7OztRQVd4QyxjQUFTLEdBQVcsT0FBTyxDQUFDOzs7O1FBUTVCLFlBQU8sR0FBWSxLQUFLLENBQUM7Ozs7UUFJekIsaUJBQVksR0FBWSxJQUFJLENBQUM7Ozs7UUFJN0Isa0JBQWEsR0FBWSxJQUFJLENBQUM7Ozs7UUFJOUIsaUJBQVksR0FBWSxJQUFJLENBQUM7Ozs7Ozs7UUFPN0IsY0FBUyxHQUFhLElBQUksQ0FBQyxjQUFjLENBQUM7Ozs7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QUFpQjtpQ0FJOUIsU0FBUyxTQUFDLG9CQUFvQjs7Ozs7OztJQW5FL0IsMkNBQzJCOzs7Ozs7SUFJM0IscUNBQ3dDOzs7OztJQUd4QyxxQ0FDa0I7Ozs7O0lBR2xCLHdDQUNvQjs7Ozs7SUFHcEIsa0NBQ3dDOzs7Ozs7SUFNeEMseUNBQytCOzs7OztJQUcvQixzQ0FDNEI7Ozs7O0lBRzVCLDJDQUN5Qjs7Ozs7SUFHekIsb0NBQ3lCOzs7OztJQUd6Qix5Q0FDNkI7Ozs7O0lBRzdCLDBDQUM4Qjs7Ozs7SUFHOUIseUNBQzZCOzs7Ozs7OztJQU03QixzQ0FDMEM7Ozs7O0lBRzFDLHdDQUMyRTs7Ozs7SUFHM0Usc0NBQ3dDOzs7OztJQUd4QywrQ0FDK0I7Ozs7O0lBRy9CLDRDQUE0Qjs7Ozs7SUFHNUIsbUNBQXdCOzs7OztJQUd4QiwyQ0FBdUI7Ozs7OztJQUd2Qix1Q0FBaUU7Ozs7O0lBR2pFLHFDQUF5Qjs7Ozs7SUFHekIsc0NBQTBCOzs7OztJQUVkLGdEQUFnRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQWZ0ZXJWaWV3SW5pdCxcbiAgICBDb21wb25lbnQsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgZm9yd2FyZFJlZixcbiAgICBJbnB1dCxcbiAgICBPbkNoYW5nZXMsIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFF1ZXJ5TGlzdCxcbiAgICBTaW1wbGVDaGFuZ2VzLCBUZW1wbGF0ZVJlZixcbiAgICBWaWV3Q2hpbGQsXG4gICAgVmlld0NoaWxkcmVuLFxuICAgIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTWVudUl0ZW1EaXJlY3RpdmUgfSBmcm9tICcuLi9tZW51L21lbnUtaXRlbS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgQ29tYm9ib3hJdGVtIH0gZnJvbSAnLi9jb21ib2JveC1pdGVtJztcbmltcG9ydCB7IE1lbnVLZXlib2FyZFNlcnZpY2UgfSBmcm9tICcuLi9tZW51L21lbnUta2V5Ym9hcmQuc2VydmljZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbi8qKlxuICogQWxsb3dzIHVzZXJzIHRvIGZpbHRlciB0aHJvdWdoIHJlc3VsdHMgYW5kIHNlbGVjdCBhIHZhbHVlLlxuICpcbiAqIFN1cHBvcnRzIEFuZ3VsYXIgRm9ybXMuXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnZmQtY29tYm9ib3gnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9jb21ib2JveC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vY29tYm9ib3guY29tcG9uZW50LnNjc3MnXSxcbiAgICBwcm92aWRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBDb21ib2JveENvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBNZW51S2V5Ym9hcmRTZXJ2aWNlXG4gICAgXSxcbiAgICBob3N0OiB7XG4gICAgICAgICdbY2xhc3MuZmQtY29tYm9ib3gtY3VzdG9tLWNsYXNzXSc6ICd0cnVlJyxcbiAgICAgICAgJ1tjbGFzcy5mZC1jb21ib2JveC1pbnB1dF0nOiAndHJ1ZSdcbiAgICB9LFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmVcbn0pXG5leHBvcnQgY2xhc3MgQ29tYm9ib3hDb21wb25lbnQgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG5cbiAgICAvKiogVmFsdWVzIHRvIGJlIGZpbHRlcmVkIGluIHRoZSBzZWFyY2ggaW5wdXQuICovXG4gICAgQElucHV0KClcbiAgICBkcm9wZG93blZhbHVlczogYW55W10gPSBbXTtcblxuICAgIC8qKiBGaWx0ZXIgZnVuY3Rpb24uIEFjY2VwdHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyBhbmQgYSBzZWFyY2ggdGVybSBhcyBhcmd1bWVudHNcbiAgICAgKiBhbmQgcmV0dXJucyBhIHN0cmluZy4gU2VlIHNlYXJjaCBpbnB1dCBleGFtcGxlcyBmb3IgZGV0YWlscy4gKi9cbiAgICBASW5wdXQoKVxuICAgIGZpbHRlckZuOiBGdW5jdGlvbiA9IHRoaXMuZGVmYXVsdEZpbHRlcjtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBzZWFyY2ggaW5wdXQgaXMgZGlzYWJsZWQuICoqL1xuICAgIEBJbnB1dCgpXG4gICAgZGlzYWJsZWQ6IGJvb2xlYW47XG5cbiAgICAvKiogUGxhY2Vob2xkZXIgb2YgdGhlIHNlYXJjaCBpbnB1dC4gKiovXG4gICAgQElucHV0KClcbiAgICBwbGFjZWhvbGRlcjogc3RyaW5nO1xuXG4gICAgLyoqIEljb24gdG8gZGlzcGxheSBpbiB0aGUgcmlnaHQtc2lkZSBidXR0b24uICovXG4gICAgQElucHV0KClcbiAgICBnbHlwaDogc3RyaW5nID0gJ25hdmlnYXRpb24tZG93bi1hcnJvdyc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdGVtcGxhdGUgd2l0aCB3aGljaCB0byBkaXNwbGF5IHRoZSBpbmRpdmlkdWFsIGxpc3RlZCBpdGVtcy5cbiAgICAgKiBVc2UgaXQgYnkgcGFzc2luZyBhbiBuZy10ZW1wbGF0ZSB3aXRoIGltcGxpY2l0IGNvbnRlbnQuIFNlZSBleGFtcGxlcyBmb3IgbW9yZSBpbmZvLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgaXRlbVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gICAgLyoqIE1heCBoZWlnaHQgb2YgdGhlIHBvcG92ZXIuIEFueSBvdmVyZmxvd2luZyBlbGVtZW50cyB3aWxsIGJlIGFjY2Vzc2libGUgdGhyb3VnaCBzY3JvbGxpbmcuICovXG4gICAgQElucHV0KClcbiAgICBtYXhIZWlnaHQ6IHN0cmluZyA9ICcyMDBweCc7XG5cbiAgICAvKiogU2VhcmNoIGZ1bmN0aW9uIHRvIGV4ZWN1dGUgd2hlbiB0aGUgRW50ZXIga2V5IGlzIHByZXNzZWQgb24gdGhlIG1haW4gaW5wdXQuICovXG4gICAgQElucHV0KClcbiAgICBzZWFyY2hGdW5jdGlvbjogRnVuY3Rpb247XG5cbiAgICAvKiogV2hldGhlciB0aGUgc2VhcmNoIGlucHV0IHNob3VsZCBiZSBkaXNwbGF5ZWQgaW4gY29tcGFjdCBtb2RlLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgY29tcGFjdDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIG1hdGNoaW5nIHN0cmluZyBzaG91bGQgYmUgaGlnaGxpZ2h0ZWQgZHVyaW5nIGZpbHRyYXRpb24uICovXG4gICAgQElucHV0KClcbiAgICBoaWdobGlnaHRpbmc6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIHBvcG92ZXIgc2hvdWxkIGNsb3NlIHdoZW4gYSB1c2VyIHNlbGVjdHMgYSByZXN1bHQuICovXG4gICAgQElucHV0KClcbiAgICBjbG9zZU9uU2VsZWN0OiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBpbnB1dCBmaWVsZCBzaG91bGQgYmUgcG9wdWxhdGVkIHdpdGggdGhlIHJlc3VsdCBwaWNrZWQgYnkgdGhlIHVzZXIuICovXG4gICAgQElucHV0KClcbiAgICBmaWxsT25TZWxlY3Q6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIERpc3BsYXkgZnVuY3Rpb24uIEFjY2VwdHMgYW4gb2JqZWN0IG9mIHRoZSBzYW1lIHR5cGUgYXMgdGhlXG4gICAgICogaXRlbXMgcGFzc2VkIHRvIGRyb3Bkb3duVmFsdWVzIGFzIGFyZ3VtZW50LCBhbmQgb3V0cHV0cyBhIHN0cmluZy5cbiAgICAgKiBBbiBhcnJvdyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBhY2Nlc3MgdGhlICp0aGlzKiBrZXl3b3JkIGluIHRoZSBjYWxsaW5nIGNvbXBvbmVudC5cbiAgICAgKiBTZWUgc2VhcmNoIGlucHV0IGV4YW1wbGVzIGZvciBkZXRhaWxzLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZGlzcGxheUZuOiBGdW5jdGlvbiA9IHRoaXMuZGVmYXVsdERpc3BsYXk7XG5cbiAgICAvKiogRXZlbnQgZW1pdHRlZCB3aGVuIGFuIGl0ZW0gaXMgY2xpY2tlZC4gVXNlICokZXZlbnQqIHRvIHJldHJpZXZlIGl0LiAqL1xuICAgIEBPdXRwdXQoKVxuICAgIGl0ZW1DbGlja2VkOiBFdmVudEVtaXR0ZXI8Q29tYm9ib3hJdGVtPiA9IG5ldyBFdmVudEVtaXR0ZXI8Q29tYm9ib3hJdGVtPigpO1xuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBAVmlld0NoaWxkcmVuKE1lbnVJdGVtRGlyZWN0aXZlKVxuICAgIG1lbnVJdGVtczogUXVlcnlMaXN0PE1lbnVJdGVtRGlyZWN0aXZlPjtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgQFZpZXdDaGlsZCgnc2VhcmNoSW5wdXRFbGVtZW50JylcbiAgICBzZWFyY2hJbnB1dEVsZW1lbnQ6IEVsZW1lbnRSZWY7XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIGRpc3BsYXllZFZhbHVlczogYW55W10gPSBbXTtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgaXNPcGVuOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIGlucHV0VGV4dFZhbHVlOiBzdHJpbmc7XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgb25EZXN0cm95JDogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uQ2hhbmdlOiBhbnkgPSAoKSA9PiB7fTtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgb25Ub3VjaGVkOiBhbnkgPSAoKSA9PiB7fTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgbWVudUtleWJvYXJkU2VydmljZTogTWVudUtleWJvYXJkU2VydmljZSkge31cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLmRyb3Bkb3duVmFsdWVzKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZFZhbHVlcyA9IHRoaXMuZHJvcGRvd25WYWx1ZXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuZHJvcGRvd25WYWx1ZXMgJiYgKGNoYW5nZXMuZHJvcGRvd25WYWx1ZXMgfHwgY2hhbmdlcy5zZWFyY2hUZXJtKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRUZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwbGF5ZWRWYWx1ZXMgPSB0aGlzLmZpbHRlckZuKHRoaXMuZHJvcGRvd25WYWx1ZXMsIHRoaXMuaW5wdXRUZXh0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwbGF5ZWRWYWx1ZXMgPSB0aGlzLmRyb3Bkb3duVmFsdWVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25EZXN0cm95JC5uZXh0KCk7XG4gICAgICAgIHRoaXMub25EZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lbnVLZXlib2FyZFNlcnZpY2UuaXRlbUNsaWNrZWRcbiAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLm9uRGVzdHJveSQpKVxuICAgICAgICAgICAgLnN1YnNjcmliZShpbmRleCA9PiB0aGlzLm9uTWVudUNsaWNrSGFuZGxlcihpbmRleCkpO1xuICAgICAgICB0aGlzLm1lbnVLZXlib2FyZFNlcnZpY2UuZm9jdXNFc2NhcGVCZWZvcmVMaXN0ID0gKCkgPT4gdGhpcy5zZWFyY2hJbnB1dEVsZW1lbnQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgICAgICB0aGlzLm1lbnVLZXlib2FyZFNlcnZpY2UuZm9jdXNFc2NhcGVBZnRlckxpc3QgPSAoKSA9PiB7fTtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uSW5wdXRLZXlkb3duSGFuZGxlcihldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQuY29kZSA9PT0gJ0VudGVyJyAmJiB0aGlzLnNlYXJjaEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlYXJjaEZ1bmN0aW9uKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQuY29kZSA9PT0gJ0Fycm93RG93bicpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5tZW51SXRlbXMgJiYgdGhpcy5tZW51SXRlbXMuZmlyc3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1lbnVJdGVtcy5maXJzdC5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBvbklucHV0S2V5dXBIYW5kbGVyKCkge1xuICAgICAgICBpZiAodGhpcy5pbnB1dFRleHQgJiYgdGhpcy5pbnB1dFRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uTWVudUtleWRvd25IYW5kbGVyKGV2ZW50OiBLZXlib2FyZEV2ZW50LCBpbmRleDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMubWVudUtleWJvYXJkU2VydmljZS5rZXlEb3duSGFuZGxlcihldmVudCwgaW5kZXgsIHRoaXMubWVudUl0ZW1zLnRvQXJyYXkoKSk7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBvbk1lbnVDbGlja0hhbmRsZXIoaW5kZXg6IG51bWJlcikge1xuICAgICAgICBjb25zdCBzZWxlY3RlZEl0ZW0gPSB0aGlzLmRpc3BsYXllZFZhbHVlc1tpbmRleF07XG4gICAgICAgIGlmIChzZWxlY3RlZEl0ZW0pIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlQ2xpY2tBY3Rpb25zKHNlbGVjdGVkSXRlbSk7XG4gICAgICAgICAgICB0aGlzLml0ZW1DbGlja2VkLmVtaXQoeyBpdGVtOiBzZWxlY3RlZEl0ZW0sIGluZGV4OiBpbmRleCB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBHZXQgdGhlIGlucHV0IHRleHQgb2YgdGhlIGlucHV0LiAqL1xuICAgIGdldCBpbnB1dFRleHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlucHV0VGV4dFZhbHVlO1xuICAgIH1cblxuICAgIC8qKiBTZXQgdGhlIGlucHV0IHRleHQgb2YgdGhlIGlucHV0LiAqL1xuICAgIHNldCBpbnB1dFRleHQodmFsdWUpIHtcbiAgICAgICAgdGhpcy5pbnB1dFRleHRWYWx1ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLm9uQ2hhbmdlKHZhbHVlKTtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHdyaXRlVmFsdWUodmFsdWU6IGFueSkge1xuICAgICAgICB0aGlzLmlucHV0VGV4dFZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICByZWdpc3Rlck9uQ2hhbmdlKGZuKSB7XG4gICAgICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHJlZ2lzdGVyT25Ub3VjaGVkKGZuKSB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBoYW5kbGVTZWFyY2hUZXJtQ2hhbmdlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRpc3BsYXllZFZhbHVlcyA9IHRoaXMuZmlsdGVyRm4odGhpcy5kcm9wZG93blZhbHVlcywgdGhpcy5pbnB1dFRleHQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZGVmYXVsdERpc3BsYXkoc3RyOiBhbnkpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH1cblxuICAgIHByaXZhdGUgZGVmYXVsdEZpbHRlcihjb250ZW50QXJyYXk6IGFueVtdLCBzZWFyY2hUZXJtOiBzdHJpbmcpOiBhbnlbXSB7XG4gICAgICAgIGNvbnN0IHNlYXJjaExvd2VyID0gc2VhcmNoVGVybS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICByZXR1cm4gY29udGVudEFycmF5LmZpbHRlcihpdGVtID0+IHtcbiAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheUZuKGl0ZW0pLnRvTG9jYWxlTG93ZXJDYXNlKCkuaW5jbHVkZXMoc2VhcmNoTG93ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZUNsaWNrQWN0aW9ucyh0ZXJtKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmNsb3NlT25TZWxlY3QpIHtcbiAgICAgICAgICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZmlsbE9uU2VsZWN0KSB7XG4gICAgICAgICAgICB0aGlzLmlucHV0VGV4dCA9IHRoaXMuZGlzcGxheUZuKHRlcm0pO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVTZWFyY2hUZXJtQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbn1cbiJdfQ==