ngx-bootstrap-multiselect-dropdown
Version:
Simple multiselect dropdown based on bootstrap 4 dropdown component.
322 lines (321 loc) • 30.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, forwardRef, Input, Output, EventEmitter, HostListener } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { DropdownSettings } from './dropdown-settings';
/** @type {?} */
export const DROPDOWN_CONTROL_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((/**
* @return {?}
*/
() => NgxBootstrapMultiselectDropdownComponent)),
multi: true
};
export class NgxBootstrapMultiselectDropdownComponent {
constructor() {
this.items = [];
this.onDataSelect = new EventEmitter();
this.onDataOperationSelect = new EventEmitter();
this.onSelectAllData = new EventEmitter();
this.onDeselectAllData = new EventEmitter();
this.filteredItems = [];
this.filterValue = '';
this.isVisible = false;
this.selectedItems = []; // Used to keep track if items currently selected. Dropdown item ids are stored
// ControlValueAccessor methods
this.onChange = (/**
* @param {?} selectedObject
* @return {?}
*/
(selectedObject) => { });
this.onTouched = (/**
* @return {?}
*/
() => { });
}
// Used to keep track if items currently selected. Dropdown item ids are stored
// Close dropdown when clicking outside component
/**
* @return {?}
*/
clickOutsideComponent() {
if (this.isVisible)
this.isVisible = false;
}
// Prevent event reaching clickOutsideComponent
/**
* @param {?} event
* @return {?}
*/
handleComponentClick(event) {
event.stopPropagation();
}
// Return selected items by filtering items array based on values in selectedItems array
/**
* @return {?}
*/
getSelectedItems() {
this.setSelectedText();
return this.items
.filter((/**
* @param {?} _
* @return {?}
*/
_ => this.selectedItems.findIndex((/**
* @param {?} x
* @return {?}
*/
x => x === _[this.innerSettings.dataIdProperty])) > -1)) // Return only items with id values in selectedItems
.slice();
}
// Set text when selecting item from dropdown
/**
* @return {?}
*/
setSelectedText() {
this.selectedText = this.selectedItems.length
? `${this.selectedItems.length} item${this.selectedItems.length > 1 ? 's' : ''} selected`
: this.innerSettings.noneSelectedBtnText;
}
// Toggle dropdown visibility
/**
* @return {?}
*/
showDropdown() {
this.isVisible = this.isVisible ? false : true;
}
// Filter items based on item name property value
/**
* @param {?} value
* @return {?}
*/
onFilterSearch(value) {
this.filterValue = value; // Save filter value so it appears when toggling dropdown
this.filteredItems = this.items.filter((/**
* @param {?} _
* @return {?}
*/
_ => _[this.innerSettings.dataNameProperty] && _[this.innerSettings.dataNameProperty].toLowerCase().startsWith(value)));
}
// Set selected dropdown item as active. Activated on dropdown item click
/**
* @param {?} selectedObject
* @return {?}
*/
onSelect(selectedObject) {
if (this.disabled)
return;
this.onTouched();
this.writeValue(selectedObject);
this.onDataSelect.emit(selectedObject);
}
// Set all dropdown items as active. Activated on select all button item click
/**
* @return {?}
*/
onSelectAll() {
if (this.disabled)
return;
this.onTouched();
this.selectedItems = this.items.map((/**
* @param {?} _
* @return {?}
*/
_ => _[this.innerSettings.dataIdProperty]));
this.writeValue(this.selectedItems);
this.onSelectAllData.emit();
}
// Remove active from all dropdown items. Activated on deselect all button item click
/**
* @return {?}
*/
onDeselectAll() {
if (this.disabled)
return;
this.onTouched();
this.selectedItems = [];
this.writeValue([]);
this.onDeselectAllData.emit();
}
// Check if number of selected items is equal or greater than limit
/**
* @return {?}
*/
isSelectionLimitReached() {
return this.innerSettings.selectionLimit && this.innerSettings.selectionLimit <= this.selectedItems.length;
}
// Check if drowdown item is active
/**
* @param {?} item
* @return {?}
*/
isActive(item) {
return this.selectedItems.findIndex((/**
* @param {?} x
* @return {?}
*/
x => x === item[this.innerSettings.dataIdProperty])) > -1;
}
// Check if input values exist in selectedItems array. If item exists remove from array, else add
/**
* @param {?} selectedObject
* @return {?}
*/
writeValue(selectedObject) {
if (selectedObject) {
/** @type {?} */
const tempArray = Array.isArray(selectedObject) ? (/** @type {?} */ (selectedObject)) : [selectedObject];
/** @type {?} */
const beforeLength = this.selectedItems.length;
if (tempArray.length === 0) {
this.selectedItems = [];
}
else {
this.items = this.items.map((/**
* @param {?} _
* @return {?}
*/
_ => {
/** @type {?} */
var index = tempArray.findIndex((/**
* @param {?} x
* @return {?}
*/
x => _[this.innerSettings.dataIdProperty] === x[this.innerSettings.dataIdProperty]));
if (index > -1) {
/** @type {?} */
const index = this.selectedItems.findIndex((/**
* @param {?} x
* @return {?}
*/
x => x === _[this.innerSettings.dataIdProperty]));
if (index > -1) {
this.selectedItems.splice(index, 1);
}
else {
if (!this.isSelectionLimitReached()) {
this.selectedItems.push(_[this.innerSettings.dataIdProperty]);
}
}
}
return _;
})).slice();
}
/** @type {?} */
const afterLength = this.selectedItems.length;
if (afterLength > beforeLength) {
this.onDataOperationSelect.emit({ operation: "added", item: selectedObject, selectedCount: this.selectedItems.length });
}
else if (afterLength < beforeLength) {
this.onDataOperationSelect.emit({ operation: "removed", item: selectedObject, selectedCount: this.selectedItems.length });
}
}
this.onChange(this.getSelectedItems());
}
/**
* @return {?}
*/
ngOnInit() {
this.innerSettings = new DropdownSettings(this.settings); // Set initial setting values
this.filteredItems = this.items; // Set initial filtered values
this.setSelectedText(); // Set initial button text
}
/**
* @param {?} isDisabled
* @return {?}
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
/**
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this.onChange = fn;
}
/**
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
}
NgxBootstrapMultiselectDropdownComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-bootstrap-multiselect',
template: `
<div class="dropdown" (click)="handleComponentClick($event)" >
<button style="text-align: right"
[disabled]="disabled"
type="button"
(click)="showDropdown()"
[ngClass]="innerSettings.btnClasses"
[style.width]="innerSettings.btnWidth">
<span style="float: left">{{selectedText}}</span>
</button>
<div *ngIf="isVisible" class="dropdown-menu pointer" [ngClass]="innerSettings.dropdownClasses" aria-labelledby="triggerId" style="display: inline-block">
<div class="dropdown-header" *ngIf="innerSettings.headerText">{{innerSettings.headerText}}</div>
<div *ngIf="innerSettings.showSelectAllBtn && !innerSettings.selectionLimit" class="dropdown-item" (click)="onSelectAll()">{{innerSettings.selectAllBtnText}}</div>
<div *ngIf="innerSettings.showDeselectAllBtn" class="dropdown-item" (click)="onDeselectAll()">{{innerSettings.deselectAllBtnText}}</div>
<div *ngIf="innerSettings.enableFilter" class="p-2"><input autocomplete="off" list="autocompleteOff" type="text" placeholder="Filter values" [value]="filterValue" (keyup)="onFilterSearch($event?.target?.value)" class="form-control form-control-sm" /></div>
<div class="dropdown-divider" *ngIf="innerSettings.showSelectAllBtn || innerSettings.showDeselectAllBtn || innerSettings.enableFilter"></div>
<div [style.height]="innerSettings.dropdownHeight" style="overflow: auto" >
<div *ngFor="let item of filteredItems; let i=index" (click)="onSelect(item)" class="dropdown-item" [ngClass]="{'active': isActive(item), 'disabled': disabled }">
{{item[innerSettings.dataNameProperty]}}
</div>
</div>
</div>
</div>
`,
providers: [DROPDOWN_CONTROL_VALUE_ACCESSOR],
styles: ['.pointer > .dropdown-item { curson: pointer; }']
}] }
];
NgxBootstrapMultiselectDropdownComponent.propDecorators = {
disabled: [{ type: Input }],
items: [{ type: Input }],
settings: [{ type: Input }],
onDataSelect: [{ type: Output }],
onDataOperationSelect: [{ type: Output }],
onSelectAllData: [{ type: Output }],
onDeselectAllData: [{ type: Output }],
clickOutsideComponent: [{ type: HostListener, args: ['document:click',] }]
};
if (false) {
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.disabled;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.items;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.settings;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.onDataSelect;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.onDataOperationSelect;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.onSelectAllData;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.onDeselectAllData;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.innerSettings;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.selectedText;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.filteredItems;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.filterValue;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.isVisible;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.selectedItems;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.onChange;
/** @type {?} */
NgxBootstrapMultiselectDropdownComponent.prototype.onTouched;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWJvb3RzdHJhcC1tdWx0aXNlbGVjdC1kcm9wZG93bi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtYm9vdHN0cmFwLW11bHRpc2VsZWN0LWRyb3Bkb3duLyIsInNvdXJjZXMiOlsibGliL25neC1ib290c3RyYXAtbXVsdGlzZWxlY3QtZHJvcGRvd24uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDekcsT0FBTyxFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDOztBQUN2RCxNQUFNLE9BQU8sK0JBQStCLEdBQVE7SUFDbEQsT0FBTyxFQUFFLGlCQUFpQjtJQUMxQixXQUFXLEVBQUUsVUFBVTs7O0lBQUMsR0FBRyxFQUFFLENBQUMsd0NBQXdDLEVBQUM7SUFDdkUsS0FBSyxFQUFFLElBQUk7Q0FDWjtBQStCRCxNQUFNLE9BQU8sd0NBQXdDO0lBOUJyRDtRQWdDa0IsVUFBSyxHQUFVLEVBQUUsQ0FBQztRQUV4QixpQkFBWSxHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFDO1FBQzFELDBCQUFxQixHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFDO1FBQ25FLG9CQUFlLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNyQyxzQkFBaUIsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBRzFDLGtCQUFhLEdBQVUsRUFBRSxDQUFDO1FBQzFCLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBQ3pCLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDbEIsa0JBQWEsR0FBVSxFQUFFLENBQUMsQ0FBQywrRUFBK0U7O1FBdUhqSCxhQUFROzs7O1FBQUcsQ0FBQyxjQUFxQixFQUFFLEVB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LGlFQUFpQzs7SUF1SGpDLDREQUF5Qzs7SUFDekMsNkRBQXFCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIGZvcndhcmRSZWYsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiwgQ29udHJvbFZhbHVlQWNjZXNzb3IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEcm9wZG93blNldHRpbmdzIH0gZnJvbSAnLi9kcm9wZG93bi1zZXR0aW5ncyc7XG5leHBvcnQgY29uc3QgRFJPUERPV05fQ09OVFJPTF9WQUxVRV9BQ0NFU1NPUjogYW55ID0ge1xuICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gTmd4Qm9vdHN0cmFwTXVsdGlzZWxlY3REcm9wZG93bkNvbXBvbmVudCksXG4gIG11bHRpOiB0cnVlXG59O1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWJvb3RzdHJhcC1tdWx0aXNlbGVjdCcsXG4gIHRlbXBsYXRlOiBgXG4gIDxkaXYgY2xhc3M9XCJkcm9wZG93blwiIChjbGljayk9XCJoYW5kbGVDb21wb25lbnRDbGljaygkZXZlbnQpXCIgPlxuICAgIDxidXR0b24gc3R5bGU9XCJ0ZXh0LWFsaWduOiByaWdodFwiXG4gICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgdHlwZT1cImJ1dHRvblwiIFxuICAgICAgKGNsaWNrKT1cInNob3dEcm9wZG93bigpXCJcbiAgICAgIFtuZ0NsYXNzXT1cImlubmVyU2V0dGluZ3MuYnRuQ2xhc3Nlc1wiXG4gICAgICBbc3R5bGUud2lkdGhdPVwiaW5uZXJTZXR0aW5ncy5idG5XaWR0aFwiPlxuICAgICAgPHNwYW4gc3R5bGU9XCJmbG9hdDogbGVmdFwiPnt7c2VsZWN0ZWRUZXh0fX08L3NwYW4+XG4gICAgICBcbiAgICA8L2J1dHRvbj5cbiAgICA8ZGl2ICpuZ0lmPVwiaXNWaXNpYmxlXCIgY2xhc3M9XCJkcm9wZG93bi1tZW51IHBvaW50ZXJcIiBbbmdDbGFzc109XCJpbm5lclNldHRpbmdzLmRyb3Bkb3duQ2xhc3Nlc1wiIGFyaWEtbGFiZWxsZWRieT1cInRyaWdnZXJJZFwiIHN0eWxlPVwiZGlzcGxheTogaW5saW5lLWJsb2NrXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZHJvcGRvd24taGVhZGVyXCIgKm5nSWY9XCJpbm5lclNldHRpbmdzLmhlYWRlclRleHRcIj57e2lubmVyU2V0dGluZ3MuaGVhZGVyVGV4dH19PC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiaW5uZXJTZXR0aW5ncy5zaG93U2VsZWN0QWxsQnRuICYmICFpbm5lclNldHRpbmdzLnNlbGVjdGlvbkxpbWl0XCIgY2xhc3M9XCJkcm9wZG93bi1pdGVtXCIgKGNsaWNrKT1cIm9uU2VsZWN0QWxsKClcIj57e2lubmVyU2V0dGluZ3Muc2VsZWN0QWxsQnRuVGV4dH19PC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiaW5uZXJTZXR0aW5ncy5zaG93RGVzZWxlY3RBbGxCdG5cIiBjbGFzcz1cImRyb3Bkb3duLWl0ZW1cIiAoY2xpY2spPVwib25EZXNlbGVjdEFsbCgpXCI+e3tpbm5lclNldHRpbmdzLmRlc2VsZWN0QWxsQnRuVGV4dH19PC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiaW5uZXJTZXR0aW5ncy5lbmFibGVGaWx0ZXJcIiBjbGFzcz1cInAtMlwiPjxpbnB1dCBhdXRvY29tcGxldGU9XCJvZmZcIiBsaXN0PVwiYXV0b2NvbXBsZXRlT2ZmXCIgdHlwZT1cInRleHRcIiBwbGFjZWhvbGRlcj1cIkZpbHRlciB2YWx1ZXNcIiBbdmFsdWVdPVwiZmlsdGVyVmFsdWVcIiAoa2V5dXApPVwib25GaWx0ZXJTZWFyY2goJGV2ZW50Py50YXJnZXQ/LnZhbHVlKVwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGZvcm0tY29udHJvbC1zbVwiIC8+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiZHJvcGRvd24tZGl2aWRlclwiICpuZ0lmPVwiaW5uZXJTZXR0aW5ncy5zaG93U2VsZWN0QWxsQnRuIHx8IGlubmVyU2V0dGluZ3Muc2hvd0Rlc2VsZWN0QWxsQnRuIHx8IGlubmVyU2V0dGluZ3MuZW5hYmxlRmlsdGVyXCI+PC9kaXY+XG4gICAgICA8ZGl2IFtzdHlsZS5oZWlnaHRdPVwiaW5uZXJTZXR0aW5ncy5kcm9wZG93bkhlaWdodFwiIHN0eWxlPVwib3ZlcmZsb3c6IGF1dG9cIiA+XG4gICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZmlsdGVyZWRJdGVtczsgbGV0IGk9aW5kZXhcIiAoY2xpY2spPVwib25TZWxlY3QoaXRlbSlcIiBjbGFzcz1cImRyb3Bkb3duLWl0ZW1cIiBbbmdDbGFzc109XCJ7J2FjdGl2ZSc6IGlzQWN0aXZlKGl0ZW0pLCAnZGlzYWJsZWQnOiBkaXNhYmxlZCB9XCI+XG4gICAgICAgICAge3tpdGVtW2lubmVyU2V0dGluZ3MuZGF0YU5hbWVQcm9wZXJ0eV19fSAgICAgICAgICAgIFxuICAgICAgICA8L2Rpdj4gICAgXG4gICAgICA8L2Rpdj4gIFxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbJy5wb2ludGVyID4gLmRyb3Bkb3duLWl0ZW0geyBjdXJzb246IHBvaW50ZXI7IH0nXSxcbiAgcHJvdmlkZXJzOiBbRFJPUERPV05fQ09OVFJPTF9WQUxVRV9BQ0NFU1NPUl1cbn0pXG5leHBvcnQgY2xhc3MgTmd4Qm9vdHN0cmFwTXVsdGlzZWxlY3REcm9wZG93bkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuICBASW5wdXQoKSBwdWJsaWMgZGlzYWJsZWQ6IGJvb2xlYW47XG4gIEBJbnB1dCgpIHB1YmxpYyBpdGVtczogYW55W10gPSBbXTtcbiAgQElucHV0KCkgcHVibGljIHNldHRpbmdzOiBhbnk7XG4gIEBPdXRwdXQoKSBvbkRhdGFTZWxlY3Q6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBvbkRhdGFPcGVyYXRpb25TZWxlY3Q6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBvblNlbGVjdEFsbERhdGEgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBvbkRlc2VsZWN0QWxsRGF0YSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIGlubmVyU2V0dGluZ3M6IERyb3Bkb3duU2V0dGluZ3M7XG4gIHB1YmxpYyBzZWxlY3RlZFRleHQ6IHN0cmluZztcbiAgcHVibGljIGZpbHRlcmVkSXRlbXM6IGFueVtdID0gW107XG4gIHB1YmxpYyBmaWx0ZXJWYWx1ZTogc3RyaW5nID0gJyc7XG4gIHB1YmxpYyBpc1Zpc2libGUgPSBmYWxzZTtcbiAgcHVibGljIHNlbGVjdGVkSXRlbXM6IGFueVtdID0gW107IC8vIFVzZWQgdG8ga2VlcCB0cmFjayBpZiBpdGVtcyBjdXJyZW50bHkgc2VsZWN0ZWQuIERyb3Bkb3duIGl0ZW0gaWRzIGFyZSBzdG9yZWRcblxuICAvLyBDbG9zZSBkcm9wZG93biB3aGVuIGNsaWNraW5nIG91dHNpZGUgY29tcG9uZW50XG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJykgY2xpY2tPdXRzaWRlQ29tcG9uZW50KCkge1xuICAgIGlmKHRoaXMuaXNWaXNpYmxlKSB0aGlzLmlzVmlzaWJsZSA9IGZhbHNlO1xuICB9XG5cbiAgLy8gUHJldmVudCBldmVudCByZWFjaGluZyBjbGlja091dHNpZGVDb21wb25lbnQgXG4gIGhhbmRsZUNvbXBvbmVudENsaWNrKGV2ZW50OiBFdmVudCkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyBcbiAgfVxuXG4gIC8vIFJldHVybiBzZWxlY3RlZCBpdGVtcyBieSBmaWx0ZXJpbmcgaXRlbXMgYXJyYXkgYmFzZWQgb24gdmFsdWVzIGluIHNlbGVjdGVkSXRlbXMgYXJyYXlcbiAgZ2V0U2VsZWN0ZWRJdGVtcygpIHsgXG4gICAgdGhpcy5zZXRTZWxlY3RlZFRleHQoKTtcbiAgICByZXR1cm4gdGhpcy5pdGVtc1xuICAgICAgLmZpbHRlcihfID0+IHRoaXMuc2VsZWN0ZWRJdGVtcy5maW5kSW5kZXgoeCA9PiB4ID09PSBfW3RoaXMuaW5uZXJTZXR0aW5ncy5kYXRhSWRQcm9wZXJ0eV0pID4gLTEpIC8vIFJldHVybiBvbmx5IGl0ZW1zIHdpdGggaWQgdmFsdWVzIGluIHNlbGVjdGVkSXRlbXNcbiAgICAgIC5zbGljZSgpO1xuICB9XG5cbiAgLy8gU2V0IHRleHQgd2hlbiBzZWxlY3RpbmcgaXRlbSBmcm9tIGRyb3Bkb3duXG4gIHNldFNlbGVjdGVkVGV4dCgpIHtcbiAgICB0aGlzLnNlbGVjdGVkVGV4dCA9IHRoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggXG4gICAgICA/IGAke3RoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGh9IGl0ZW0ke3RoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPiAxID8gJ3MnIDogJyd9IHNlbGVjdGVkYCBcbiAgICAgIDogdGhpcy5pbm5lclNldHRpbmdzLm5vbmVTZWxlY3RlZEJ0blRleHQ7XG4gIH1cblxuICAvLyBUb2dnbGUgZHJvcGRvd24gdmlzaWJpbGl0eVxuICBzaG93RHJvcGRvd24oKSB7XG4gICAgdGhpcy5pc1Zpc2libGUgPSB0aGlzLmlzVmlzaWJsZSA/IGZhbHNlIDogdHJ1ZTtcbiAgfVxuXG4gIC8vIEZpbHRlciBpdGVtcyBiYXNlZCBvbiBpdGVtIG5hbWUgcHJvcGVydHkgdmFsdWVcbiAgb25GaWx0ZXJTZWFyY2godmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuZmlsdGVyVmFsdWUgPSB2YWx1ZTsgLy8gU2F2ZSBmaWx0ZXIgdmFsdWUgc28gaXQgYXBwZWFycyB3aGVuIHRvZ2dsaW5nIGRyb3Bkb3duXG4gICAgdGhpcy5maWx0ZXJlZEl0ZW1zID0gdGhpcy5pdGVtcy5maWx0ZXIoXyA9PiBfW3RoaXMuaW5uZXJTZXR0aW5ncy5kYXRhTmFtZVByb3BlcnR5XSAmJiBfW3RoaXMuaW5uZXJTZXR0aW5ncy5kYXRhTmFtZVByb3BlcnR5XS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgodmFsdWUpKTtcbiAgfVxuXG4gIC8vIFNldCBzZWxlY3RlZCBkcm9wZG93biBpdGVtIGFzIGFjdGl2ZS4gQWN0aXZhdGVkIG9uIGRyb3Bkb3duIGl0ZW0gY2xpY2tcbiAgb25TZWxlY3Qoc2VsZWN0ZWRPYmplY3Q6IGFueSkge1xuICAgIGlmKHRoaXMuZGlzYWJsZWQpIHJldHVybjtcblxuICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgdGhpcy53cml0ZVZhbHVlKHNlbGVjdGVkT2JqZWN0KTsgICAgXG4gICAgdGhpcy5vbkRhdGFTZWxlY3QuZW1pdChzZWxlY3RlZE9iamVjdCk7XG4gIH1cblxuICAvLyBTZXQgYWxsIGRyb3Bkb3duIGl0ZW1zIGFzIGFjdGl2ZS4gQWN0aXZhdGVkIG9uIHNlbGVjdCBhbGwgYnV0dG9uIGl0ZW0gY2xpY2tcbiAgb25TZWxlY3RBbGwoKSB7XG4gICAgaWYodGhpcy5kaXNhYmxlZCkgcmV0dXJuO1xuXG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB0aGlzLnNlbGVjdGVkSXRlbXMgPSB0aGlzLml0ZW1zLm1hcChfID0+IF9bdGhpcy5pbm5lclNldHRpbmdzLmRhdGFJZFByb3BlcnR5XSk7XG4gICAgdGhpcy53cml0ZVZhbHVlKHRoaXMuc2VsZWN0ZWRJdGVtcyk7ICAgIFxuICAgIHRoaXMub25TZWxlY3RBbGxEYXRhLmVtaXQoKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSBhY3RpdmUgZnJvbSBhbGwgZHJvcGRvd24gaXRlbXMuIEFjdGl2YXRlZCBvbiBkZXNlbGVjdCBhbGwgYnV0dG9uIGl0ZW0gY2xpY2tcbiAgb25EZXNlbGVjdEFsbCgpIHtcbiAgICBpZih0aGlzLmRpc2FibGVkKSByZXR1cm47XG5cbiAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgIHRoaXMuc2VsZWN0ZWRJdGVtcyA9IFtdO1xuICAgIHRoaXMud3JpdGVWYWx1ZShbXSk7ICAgIFxuICAgIHRoaXMub25EZXNlbGVjdEFsbERhdGEuZW1pdCgpO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgbnVtYmVyIG9mIHNlbGVjdGVkIGl0ZW1zIGlzIGVxdWFsIG9yIGdyZWF0ZXIgdGhhbiBsaW1pdFxuICBpc1NlbGVjdGlvbkxpbWl0UmVhY2hlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5pbm5lclNldHRpbmdzLnNlbGVjdGlvbkxpbWl0ICYmIHRoaXMuaW5uZXJTZXR0aW5ncy5zZWxlY3Rpb25MaW1pdCA8PSB0aGlzLnNlbGVjdGVkSXRlbXMubGVuZ3RoO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgZHJvd2Rvd24gaXRlbSBpcyBhY3RpdmVcbiAgaXNBY3RpdmUoaXRlbTogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRJdGVtcy5maW5kSW5kZXgoeCA9PiB4ID09PSBpdGVtW3RoaXMuaW5uZXJTZXR0aW5ncy5kYXRhSWRQcm9wZXJ0eV0pID4gLTE7XG4gIH1cbiAgXG4gIC8vIENoZWNrIGlmIGlucHV0IHZhbHVlcyBleGlzdCBpbiBzZWxlY3RlZEl0ZW1zIGFycmF5LiBJZiBpdGVtIGV4aXN0cyByZW1vdmUgZnJvbSBhcnJheSwgZWxzZSBhZGRcbiAgd3JpdGVWYWx1ZShzZWxlY3RlZE9iamVjdDogYW55KSB7ICAgXG4gICAgaWYoc2VsZWN0ZWRPYmplY3QpIHsgICBcbiAgICAgIGNvbnN0IHRlbXBBcnJheSA9IEFycmF5LmlzQXJyYXkoc2VsZWN0ZWRPYmplY3QpID8gc2VsZWN0ZWRPYmplY3QgYXMgYW55W10gOiBbc2VsZWN0ZWRPYmplY3RdO1xuICAgICAgY29uc3QgYmVmb3JlTGVuZ3RoID0gdGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aDtcbiAgICAgIGlmKHRlbXBBcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZEl0ZW1zID0gW107XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5pdGVtcyA9IHRoaXMuaXRlbXMubWFwKF8gPT4ge1xuICAgICAgICAgIHZhciBpbmRleCA9IHRlbXBBcnJheS5maW5kSW5kZXgoeCA9PiBfW3RoaXMuaW5uZXJTZXR0aW5ncy5kYXRhSWRQcm9wZXJ0eV0gPT09IHhbdGhpcy5pbm5lclNldHRpbmdzLmRhdGFJZFByb3BlcnR5XSk7XG4gICAgICAgICAgaWYoaW5kZXggPiAtMSkgeyBcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5zZWxlY3RlZEl0ZW1zLmZpbmRJbmRleCh4ID0+IHggPT09IF9bdGhpcy5pbm5lclNldHRpbmdzLmRhdGFJZFByb3BlcnR5XSk7XG4gICAgICAgICAgICBpZihpbmRleCA+IC0xKSB7IFxuICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkSXRlbXMuc3BsaWNlKGluZGV4LCAxKTsgXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZighdGhpcy5pc1NlbGVjdGlvbkxpbWl0UmVhY2hlZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEl0ZW1zLnB1c2goX1t0aGlzLmlubmVyU2V0dGluZ3MuZGF0YUlkUHJvcGVydHldKTsgXG4gICAgICAgICAgICAgIH0gIFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgXG4gICAgICAgICAgcmV0dXJuIF87XG4gICAgICAgIH0pLnNsaWNlKCk7ICAgICBcbiAgICAgIH0gIFxuICAgICAgY29uc3QgYWZ0ZXJMZW5ndGggPSB0aGlzLnNlbGVjdGVkSXRlbXMubGVuZ3RoO1xuICAgICAgaWYgKGFmdGVyTGVuZ3RoID4gYmVmb3JlTGVuZ3RoKSB7XG4gICAgICAgIHRoaXMub25EYXRhT3BlcmF0aW9uU2VsZWN0LmVtaXQoeyBvcGVyYXRpb246IFwiYWRkZWRcIiwgaXRlbTogc2VsZWN0ZWRPYmplY3QsIHNlbGVjdGVkQ291bnQ6IHRoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggfSk7XG4gICAgICB9IGVsc2UgaWYgKGFmdGVyTGVuZ3RoIDwgYmVmb3JlTGVuZ3RoKSB7XG4gICAgICAgIHRoaXMub25EYXRhT3BlcmF0aW9uU2VsZWN0LmVtaXQoeyBvcGVyYXRpb246IFwicmVtb3ZlZFwiLCBpdGVtOiBzZWxlY3RlZE9iamVjdCwgc2VsZWN0ZWRDb3VudDogdGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aCB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5vbkNoYW5nZSh0aGlzLmdldFNlbGVjdGVkSXRlbXMoKSk7XG4gIH1cblxuICBuZ09uSW5pdCgpIHsgXG4gICAgdGhpcy5pbm5lclNldHRpbmdzID0gbmV3IERyb3Bkb3duU2V0dGluZ3ModGhpcy5zZXR0aW5ncyk7IC8vIFNldCBpbml0aWFsIHNldHRpbmcgdmFsdWVzXG4gICAgdGhpcy5maWx0ZXJlZEl0ZW1zID0gdGhpcy5pdGVtczsgLy8gU2V0IGluaXRpYWwgZmlsdGVyZWQgdmFsdWVzXG4gICAgdGhpcy5zZXRTZWxlY3RlZFRleHQoKTsgLy8gU2V0IGluaXRpYWwgYnV0dG9uIHRleHRcbiAgfVxuXG4gIC8vIENvbnRyb2xWYWx1ZUFjY2Vzc29yIG1ldGhvZHNcbiAgb25DaGFuZ2UgPSAoc2VsZWN0ZWRPYmplY3Q6IGFueVtdKSA9PiB7fTtcbiAgb25Ub3VjaGVkID0gKCkgPT4ge307XG4gIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuICB9XG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSkge1xuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgfVxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KSB7XG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgfSBcbn1cblxuIl19