@kolkov/ngx-dadata
Version:
Angular 6+ and 13+ DaData suggestion (подсказки) implementation
237 lines • 31.6 kB
JavaScript
import { Component, EventEmitter, forwardRef, HostListener, Inject, Input, Output, ViewChild } from '@angular/core';
import { DadataType } from './ngx-dadata.service';
import { Subject, timer } from 'rxjs';
import { debounce } from 'rxjs/operators';
import { DadataConfigDefault } from './dadata-config';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { DOCUMENT } from '@angular/common';
import { unwrapHtmlForSink } from 'safevalues';
import { createHtml } from 'safevalues/implementation/html_impl';
import * as i0 from "@angular/core";
import * as i1 from "./ngx-dadata.service";
import * as i2 from "@angular/forms";
import * as i3 from "@angular/common";
/*const NGX_DADATA_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => NgxDadataComponent),
multi: true,
};*/
export function createDaDataValidator(value) {
return (c) => {
const err = {
rangeError: {
given: c.value,
expected: value,
}
};
return (c.value !== value) ? err : null;
};
}
/**
* Autocomplete IDs need to be unique across components, so this counter exists outside of
* the component definition.
*/
let uniqueDadataIdCounter = 0;
export class NgxDadataComponent {
constructor(dataService, r, elRef, document) {
this.dataService = dataService;
this.r = r;
this.elRef = elRef;
this.document = document;
this.v = '';
this.currentFocus = -1;
this.opened = false;
this.data = [];
this.config = DadataConfigDefault;
this.disabled = null;
this.type = DadataType.address;
this.limit = DadataConfigDefault.limit;
this.placeholder = '';
this.locations = null;
this.selected = new EventEmitter();
this.inputString$ = new Subject();
/** Unique ID to be used by autocomplete trigger's "aria-owns" property. */
this.id = `ngx-dadata-${uniqueDadataIdCounter++}`;
// onSuggestionSelected = (value: string) => {};
this.onTouched = () => { };
this.propagateChange = () => { };
this.validateFn = () => { };
}
get value() {
return this.v;
}
set value(v) {
if (v !== this.v) {
this.v = v;
this.propagateChange(v);
}
}
ngOnInit() {
/*this.validateFn = createDaDataValidator(this._value);
this.propagateChange(this._value);*/
this.type = this.config.type;
this.locations = this.config.locations;
this.dataService.setApiKey(this.apiKey ? this.apiKey : this.config.apiKey);
this.inputString$.pipe(debounce(() => timer(this.config.delay ? this.config.delay : 500))).subscribe(x => {
this.dataService.getData(x, this.type, this.config)
.subscribe((y) => {
this.data = y.suggestions;
if (this.data.length) {
this.opened = true;
}
});
});
}
ngOnChanges(changes) {
if (changes.value) {
// console.log('ngOnChanges');
}
}
getData(value) {
this.inputString$.next(value);
this.currentFocus = -1;
}
onClick(e, item) {
this.inputValue.nativeElement.value = item.value;
this.propagateChange(item.value);
this.inputValue.nativeElement.focus();
this.selectedSuggestion = item;
this.data = [];
this.currentFocus = -1;
this.opened = false;
this.selected.emit(item);
// this.selectedData.emit(item.data);
// this.selectedString.emit(item.value);
}
onOutsideClick($event) {
if (!this.opened) {
return;
}
if (!this.elRef.nativeElement.contains($event.target)) {
this.data = [];
this.opened = false;
}
}
onArrowDown() {
this.removeFocus(this.currentFocus);
if (this.currentFocus >= this.data.length - 1) {
this.currentFocus = 0;
}
else {
this.currentFocus++;
}
this.setFocus(this.currentFocus);
}
onArrowUp() {
this.removeFocus(this.currentFocus);
if (this.currentFocus === 0) {
this.currentFocus = this.data.length - 1;
}
else {
this.currentFocus--;
}
this.setFocus(this.currentFocus);
}
onEnter(event) {
this.selectedSuggestion = this.data[this.currentFocus];
this.inputValue.nativeElement.value = this.selectedSuggestion.value;
this.data = [];
this.currentFocus = -1;
this.propagateChange(this.selectedSuggestion.value);
this.selected.emit(this.selectedSuggestion);
// this.selectedData.emit(this.selectedSuggestion.data);
// this.selectedString.emit(this.selectedSuggestion.value);
}
setFocus(id) {
const activeEl = this.document.getElementById(id + 'item');
this.r.addClass(activeEl, 'active');
}
removeFocus(id) {
if (id !== -1) {
const activeEl = this.document.getElementById(id + 'item');
this.r.removeClass(activeEl, 'active');
}
}
writeValue(value) {
if (value !== undefined && value !== null) {
this.v = value;
}
else {
this.v = '';
}
this.r.setProperty(this.inputValue.nativeElement, 'innerHTML', unwrapHtmlForSink(createHtml(this.v)));
}
/**
* Set the function to be called
* when the control receives a change event.
*
* @param fn a function
*/
registerOnChange(fn) {
// this.onSuggestionSelected = fn;
this.propagateChange = fn;
}
/**
* Set the function to be called
* when the control receives a touch event.
*
* @param fn a function
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* Implements disabled state for this element
*
* @param isDisabled Disabled state flag
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
}
NgxDadataComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: NgxDadataComponent, deps: [{ token: i1.NgxDadataService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component });
NgxDadataComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: NgxDadataComponent, selector: "ngx-dadata", inputs: { config: "config", apiKey: "apiKey", disabled: "disabled", type: "type", limit: "limit", placeholder: "placeholder", locations: "locations" }, outputs: { selectedSuggestion: "selectedSuggestion", selected: "selected" }, host: { listeners: { "document:click": "onOutsideClick($event)" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxDadataComponent),
multi: true
}, /*NGX_DADATA_VALIDATOR*/
], viewQueries: [{ propertyName: "inputValue", first: true, predicate: ["inputValue"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"autocomplete\">\n <input [disabled]=\"disabled ? true : null\" type=\"text\" class=\"search\" #inputValue (input)=\"getData(inputValue.value)\"\n [placeholder]=\"placeholder\" (keyup.ArrowDown)=\"onArrowDown()\" (keyup.ArrowUp)=\"onArrowUp()\"\n (keyup.Enter)=\"onEnter($event)\" spellcheck=\"false\" [(ngModel)]=\"value\" autocomplete=\"off\" />\n <div *ngIf=\"data.length\">\n <div class=\"autocomplete-items\">\n <div class=\"autocomplele-item\" *ngFor=\"let item of data; let i = index\" (click)=\"onClick($event, item)\" [id]=\"i+'item'\">\n {{item.value}}\n <ng-template [ngIf]=\"type==='party'\">\n <br/>\n <span>{{item.data?.inn}} {{config.partyAddress === 'full' ? item.data?.address?.value : item.data?.address?.data?.city}}</span>\n </ng-template>\n </div>\n </div>\n </div>\n</div>\n", styles: [".autocomplete{position:relative}input{border:0 solid transparent;background-color:#f1f1f1;padding:5px}input[type=text]{background-color:#f1f1f1;width:100%}input[type=submit]{background-color:#1e90ff;color:#fff}.autocomplete-items{position:absolute;border:1px solid #d4d4d4;border-bottom:none;border-top:none;z-index:99;top:100%;left:0;right:0}.autocomplete-items .autocomplele-item{padding:5px 10px;cursor:pointer;background-color:#fff;border-bottom:1px solid #d4d4d4}.autocomplete-items .autocomplele-item:hover{background-color:#e9e9e9}.autocomplete-items .autocomplele-item.active{background-color:#1e90ff!important;color:#fff}.autocomplete-items .autocomplele-item span{color:#555;font-size:80%}\n"], directives: [{ type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: NgxDadataComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-dadata', providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxDadataComponent),
multi: true
}, /*NGX_DADATA_VALIDATOR*/
], template: "<div class=\"autocomplete\">\n <input [disabled]=\"disabled ? true : null\" type=\"text\" class=\"search\" #inputValue (input)=\"getData(inputValue.value)\"\n [placeholder]=\"placeholder\" (keyup.ArrowDown)=\"onArrowDown()\" (keyup.ArrowUp)=\"onArrowUp()\"\n (keyup.Enter)=\"onEnter($event)\" spellcheck=\"false\" [(ngModel)]=\"value\" autocomplete=\"off\" />\n <div *ngIf=\"data.length\">\n <div class=\"autocomplete-items\">\n <div class=\"autocomplele-item\" *ngFor=\"let item of data; let i = index\" (click)=\"onClick($event, item)\" [id]=\"i+'item'\">\n {{item.value}}\n <ng-template [ngIf]=\"type==='party'\">\n <br/>\n <span>{{item.data?.inn}} {{config.partyAddress === 'full' ? item.data?.address?.value : item.data?.address?.data?.city}}</span>\n </ng-template>\n </div>\n </div>\n </div>\n</div>\n", styles: [".autocomplete{position:relative}input{border:0 solid transparent;background-color:#f1f1f1;padding:5px}input[type=text]{background-color:#f1f1f1;width:100%}input[type=submit]{background-color:#1e90ff;color:#fff}.autocomplete-items{position:absolute;border:1px solid #d4d4d4;border-bottom:none;border-top:none;z-index:99;top:100%;left:0;right:0}.autocomplete-items .autocomplele-item{padding:5px 10px;cursor:pointer;background-color:#fff;border-bottom:1px solid #d4d4d4}.autocomplete-items .autocomplele-item:hover{background-color:#e9e9e9}.autocomplete-items .autocomplele-item.active{background-color:#1e90ff!important;color:#fff}.autocomplete-items .autocomplele-item span{color:#555;font-size:80%}\n"] }]
}], ctorParameters: function () { return [{ type: i1.NgxDadataService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }]; }, propDecorators: { config: [{
type: Input
}], apiKey: [{
type: Input
}], disabled: [{
type: Input
}], type: [{
type: Input
}], limit: [{
type: Input
}], placeholder: [{
type: Input
}], locations: [{
type: Input
}], selectedSuggestion: [{
type: Output
}], selected: [{
type: Output
}], inputValue: [{
type: ViewChild,
args: ['inputValue', { static: true }]
}], onOutsideClick: [{
type: HostListener,
args: ['document:click', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWRhZGF0YS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZGFkYXRhL3NyYy9saWIvbmd4LWRhZGF0YS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZGFkYXRhL3NyYy9saWIvbmd4LWRhZGF0YS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULFlBQVksRUFDWixVQUFVLEVBQ1YsWUFBWSxFQUFFLE1BQU0sRUFDcEIsS0FBSyxFQUdMLE1BQU0sRUFHTixTQUFTLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLFVBQVUsRUFBbUIsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRSxPQUFPLEVBQUMsT0FBTyxFQUFFLEtBQUssRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUNwQyxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFHeEMsT0FBTyxFQUFlLG1CQUFtQixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDbEUsT0FBTyxFQUFtRCxpQkFBaUIsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ25HLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDN0MsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLHFDQUFxQyxDQUFDOzs7OztBQUUvRDs7OztJQUlJO0FBRUosTUFBTSxVQUFVLHFCQUFxQixDQUFDLEtBQUs7SUFDekMsT0FBTyxDQUFDLENBQWMsRUFBRSxFQUFFO1FBQ3hCLE1BQU0sR0FBRyxHQUFHO1lBQ1YsVUFBVSxFQUFFO2dCQUNWLEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSztnQkFDZCxRQUFRLEVBQUUsS0FBSzthQUNoQjtTQUNGLENBQUM7UUFFRixPQUFPLENBQUMs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aW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIEhvc3RMaXN0ZW5lciwgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgUmVuZGVyZXIyLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0RhZGF0YVR5cGUsIE5neERhZGF0YVNlcnZpY2V9IGZyb20gJy4vbmd4LWRhZGF0YS5zZXJ2aWNlJztcbmltcG9ydCB7U3ViamVjdCwgdGltZXJ9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtkZWJvdW5jZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtEYWRhdGFSZXNwb25zZX0gZnJvbSAnLi9tb2RlbHMvZGFkYXRhLXJlc3BvbnNlJztcbmltcG9ydCB7RGFkYXRhU3VnZ2VzdGlvbn0gZnJvbSAnLi9tb2RlbHMvc3VnZ2VzdGlvbic7XG5pbXBvcnQge0RhZGF0YUNvbmZpZywgRGFkYXRhQ29uZmlnRGVmYXVsdH0gZnJvbSAnLi9kYWRhdGEtY29uZmlnJztcbmltcG9ydCB7Q29udHJvbFZhbHVlQWNjZXNzb3IsIEZvcm1Db250cm9sLCBOR19WQUxJREFUT1JTLCBOR19WQUxVRV9BQ0NFU1NPUn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtET0NVTUVOVH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7dW53cmFwSHRtbEZvclNpbmt9IGZyb20gJ3NhZmV2YWx1ZXMnO1xuaW1wb3J0IHtjcmVhdGVIdG1sfSBmcm9tICdzYWZldmFsdWVzL2ltcGxlbWVudGF0aW9uL2h0bWxfaW1wbCc7XG5cbi8qY29uc3QgTkdYX0RBREFUQV9WQUxJREFUT1IgPSB7XG4gIHByb3ZpZGU6IE5HX1ZBTElEQVRPUlMsXG4gIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5neERhZGF0YUNvbXBvbmVudCksXG4gIG11bHRpOiB0cnVlLFxufTsqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRGFEYXRhVmFsaWRhdG9yKHZhbHVlKSB7XG4gIHJldHVybiAoYzogRm9ybUNvbnRyb2wpID0+IHtcbiAgICBjb25zdCBlcnIgPSB7XG4gICAgICByYW5nZUVycm9yOiB7XG4gICAgICAgIGdpdmVuOiBjLnZhbHVlLFxuICAgICAgICBleHBlY3RlZDogdmFsdWUsXG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiAoYy52YWx1ZSAhPT0gdmFsdWUpID8gZXJyIDogbnVsbDtcbiAgfTtcbn1cblxuLyoqXG4gKiBBdXRvY29tcGxldGUgSURzIG5lZWQgdG8gYmUgdW5pcXVlIGFjcm9zcyBjb21wb25lbnRzLCBzbyB0aGlzIGNvdW50ZXIgZXhpc3RzIG91dHNpZGUgb2ZcbiAqIHRoZSBjb21wb25lbnQgZGVmaW5pdGlvbi5cbiAqL1xubGV0IHVuaXF1ZURhZGF0YUlkQ291bnRlciA9IDA7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1kYWRhdGEnLFxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LWRhZGF0YS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL25neC1kYWRhdGEuY29tcG9uZW50LnNjc3MnXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5neERhZGF0YUNvbXBvbmVudCksXG4gICAgbXVsdGk6IHRydWVcbiAgfSwgLypOR1hfREFEQVRBX1ZBTElEQVRPUiovXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hEYWRhdGFDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkNoYW5nZXMge1xuICBwcml2YXRlIHY6IGFueSA9ICcnO1xuICBjdXJyZW50Rm9jdXMgPSAtMTtcblxuICBvcGVuZWQgPSBmYWxzZTtcblxuICBkYXRhOiBEYWRhdGFTdWdnZXN0aW9uW10gPSBbXTtcblxuICBASW5wdXQoKSBjb25maWc6IERhZGF0YUNvbmZpZyA9IERhZGF0YUNvbmZpZ0RlZmF1bHQ7XG4gIEBJbnB1dCgpIGFwaUtleTogc3RyaW5nO1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IG51bGw7XG4gIEBJbnB1dCgpIHR5cGUgPSBEYWRhdGFUeXBlLmFkZHJlc3M7XG4gIEBJbnB1dCgpIGxpbWl0ID0gRGFkYXRhQ29uZmlnRGVmYXVsdC5saW1pdDtcbiAgQElucHV0KCkgcGxhY2Vob2xkZXIgPSAnJztcbiAgQElucHV0KCkgbG9jYXRpb25zID0gbnVsbDtcblxuICBAT3V0cHV0KCkgc2VsZWN0ZWRTdWdnZXN0aW9uOiBEYWRhdGFTdWdnZXN0aW9uO1xuICBAT3V0cHV0KCkgc2VsZWN0ZWQ6IEV2ZW50RW1pdHRlcjxEYWRhdGFTdWdnZXN0aW9uPiA9IG5ldyBFdmVudEVtaXR0ZXI8RGFkYXRhU3VnZ2VzdGlvbj4oKTtcbiAgLy8gQE91dHB1dCgpIHNlbGVjdGVkRGF0YSA9IG5ldyBFdmVudEVtaXR0ZXI8RGFEYXRhQWRkcmVzcyB8IERhRGF0YUZJTyB8IERhRGF0YUJhbmsgfCBEYURhdGFQYXJ0eSB8IERhRGF0YUVtYWlsPigpO1xuICAvLyBAT3V0cHV0KCkgc2VsZWN0ZWRTdHJpbmcgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBAVmlld0NoaWxkKCdpbnB1dFZhbHVlJywgeyBzdGF0aWM6IHRydWUgfSkgaW5wdXRWYWx1ZTogRWxlbWVudFJlZjtcblxuICBwcml2YXRlIGlucHV0U3RyaW5nJCA9IG5ldyBTdWJqZWN0PHN0cmluZz4oKTtcblxuICAvKiogVW5pcXVlIElEIHRvIGJlIHVzZWQgYnkgYXV0b2NvbXBsZXRlIHRyaWdnZXIncyBcImFyaWEtb3duc1wiIHByb3BlcnR5LiAqL1xuICBpZCA9IGBuZ3gtZGFkYXRhLSR7dW5pcXVlRGFkYXRhSWRDb3VudGVyKyt9YDtcblxuICAvLyBvblN1Z2dlc3Rpb25TZWxlY3RlZCA9ICh2YWx1ZTogc3RyaW5nKSA9PiB7fTtcbiAgb25Ub3VjaGVkID0gKCkgPT4ge307XG4gIHByb3BhZ2F0ZUNoYW5nZTogYW55ID0gKCkgPT4ge307XG4gIHZhbGlkYXRlRm46IGFueSA9ICgpID0+IHt9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZGF0YVNlcnZpY2U6IE5neERhZGF0YVNlcnZpY2UsXG4gICAgcHJpdmF0ZSByOiBSZW5kZXJlcjIsXG4gICAgcHJpdmF0ZSBlbFJlZjogRWxlbWVudFJlZixcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIGRvY3VtZW50OiBEb2N1bWVudCxcbiAgICApIHtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLnY7XG4gIH1cblxuICBzZXQgdmFsdWUodjogYW55KSB7XG4gICAgaWYgKHYgIT09IHRoaXMudikge1xuICAgICAgdGhpcy52ID0gdjtcbiAgICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlKHYpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIC8qdGhpcy52YWxpZGF0ZUZuID0gY3JlYXRlRGFEYXRhVmFsaWRhdG9yKHRoaXMuX3ZhbHVlKTtcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSh0aGlzLl92YWx1ZSk7Ki9cbiAgICB0aGlzLnR5cGUgPSB0aGlzLmNvbmZpZy50eXBlO1xuICAgIHRoaXMubG9jYXRpb25zID0gdGhpcy5jb25maWcubG9jYXRpb25zO1xuICAgIHRoaXMuZGF0YVNlcnZpY2Uuc2V0QXBpS2V5KHRoaXMuYXBpS2V5ID8gdGhpcy5hcGlLZXkgOiB0aGlzLmNvbmZpZy5hcGlLZXkpO1xuICAgIHRoaXMuaW5wdXRTdHJpbmckLnBpcGUoXG4gICAgICBkZWJvdW5jZSgoKSA9PiB0aW1lcih0aGlzLmNvbmZpZy5kZWxheSA/IHRoaXMuY29uZmlnLmRlbGF5IDogNTAwKSksXG4gICAgKS5zdWJzY3JpYmUoeCA9PiB7XG4gICAgICB0aGlzLmRhdGFTZXJ2aWNlLmdldERhdGEoeCwgdGhpcy50eXBlLCB0aGlzLmNvbmZpZylcbiAgICAgICAgLnN1YnNjcmliZSgoeTogRGFkYXRhUmVzcG9uc2UpID0+IHtcbiAgICAgICAgdGhpcy5kYXRhID0geS5zdWdnZXN0aW9ucztcbiAgICAgICAgaWYgKHRoaXMuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLm9wZW5lZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgIGlmIChjaGFuZ2VzLnZhbHVlKSB7XG4gICAgICAvLyBjb25zb2xlLmxvZygnbmdPbkNoYW5nZXMnKTtcbiAgICB9XG4gIH1cblxuICBnZXREYXRhKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLmlucHV0U3RyaW5nJC5uZXh0KHZhbHVlKTtcbiAgICB0aGlzLmN1cnJlbnRGb2N1cyA9IC0xO1xuICB9XG5cbiAgb25DbGljayhlOiBNb3VzZUV2ZW50LCBpdGVtOiBEYWRhdGFTdWdnZXN0aW9uKSB7XG4gICAgdGhpcy5pbnB1dFZhbHVlLm5hdGl2ZUVsZW1lbnQudmFsdWUgPSBpdGVtLnZhbHVlO1xuICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlKGl0ZW0udmFsdWUpO1xuICAgIHRoaXMuaW5wdXRWYWx1ZS5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgdGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb24gPSBpdGVtO1xuICAgIHRoaXMuZGF0YSA9IFtdO1xuICAgIHRoaXMuY3VycmVudEZvY3VzID0gLTE7XG4gICAgdGhpcy5vcGVuZWQgPSBmYWxzZTtcbiAgICB0aGlzLnNlbGVjdGVkLmVtaXQoaXRlbSk7XG4gICAgLy8gdGhpcy5zZWxlY3RlZERhdGEuZW1pdChpdGVtLmRhdGEpO1xuICAgIC8vIHRoaXMuc2VsZWN0ZWRTdHJpbmcuZW1pdChpdGVtLnZhbHVlKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnXSlcbiAgb25PdXRzaWRlQ2xpY2soJGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgaWYgKCF0aGlzLm9wZW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuZWxSZWYubmF0aXZlRWxlbWVudC5jb250YWlucygkZXZlbnQudGFyZ2V0KSkge1xuICAgICAgdGhpcy5kYXRhID0gW107XG4gICAgICB0aGlzLm9wZW5lZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIG9uQXJyb3dEb3duKCkge1xuICAgIHRoaXMucmVtb3ZlRm9jdXModGhpcy5jdXJyZW50Rm9jdXMpO1xuICAgIGlmICh0aGlzLmN1cnJlbnRGb2N1cyA+PSB0aGlzLmRhdGEubGVuZ3RoIC0gMSkge1xuICAgICAgdGhpcy5jdXJyZW50Rm9jdXMgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmN1cnJlbnRGb2N1cysrO1xuICAgIH1cbiAgICB0aGlzLnNldEZvY3VzKHRoaXMuY3VycmVudEZvY3VzKTtcbiAgfVxuXG4gIG9uQXJyb3dVcCgpIHtcbiAgICB0aGlzLnJlbW92ZUZvY3VzKHRoaXMuY3VycmVudEZvY3VzKTtcbiAgICBpZiAodGhpcy5jdXJyZW50Rm9jdXMgPT09IDApIHtcbiAgICAgIHRoaXMuY3VycmVudEZvY3VzID0gdGhpcy5kYXRhLmxlbmd0aCAtIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY3VycmVudEZvY3VzLS07XG4gICAgfVxuICAgIHRoaXMuc2V0Rm9jdXModGhpcy5jdXJyZW50Rm9jdXMpO1xuICB9XG5cbiAgb25FbnRlcihldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uID0gdGhpcy5kYXRhW3RoaXMuY3VycmVudEZvY3VzXTtcbiAgICB0aGlzLmlucHV0VmFsdWUubmF0aXZlRWxlbWVudC52YWx1ZSA9IHRoaXMuc2VsZWN0ZWRTdWdnZXN0aW9uLnZhbHVlO1xuICAgIHRoaXMuZGF0YSA9IFtdO1xuICAgIHRoaXMuY3VycmVudEZvY3VzID0gLTE7XG4gICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb24udmFsdWUpO1xuICAgIHRoaXMuc2VsZWN0ZWQuZW1pdCh0aGlzLnNlbGVjdGVkU3VnZ2VzdGlvbik7XG4gICAgLy8gdGhpcy5zZWxlY3RlZERhdGEuZW1pdCh0aGlzLnNlbGVjdGVkU3VnZ2VzdGlvbi5kYXRhKTtcbiAgICAvLyB0aGlzLnNlbGVjdGVkU3RyaW5nLmVtaXQodGhpcy5zZWxlY3RlZFN1Z2dlc3Rpb24udmFsdWUpO1xuICB9XG5cbiAgc2V0Rm9jdXMoaWQ6IG51bWJlcikge1xuICAgIGNvbnN0IGFjdGl2ZUVsID0gdGhpcy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCArICdpdGVtJyk7XG4gICAgdGhpcy5yLmFkZENsYXNzKGFjdGl2ZUVsLCAnYWN0aXZlJyk7XG4gIH1cblxuICByZW1vdmVGb2N1cyhpZDogbnVtYmVyKSB7XG4gICAgaWYgKGlkICE9PSAtMSkge1xuICAgICAgY29uc3QgYWN0aXZlRWwgPSB0aGlzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkICsgJ2l0ZW0nKTtcbiAgICAgIHRoaXMuci5yZW1vdmVDbGFzcyhhY3RpdmVFbCwgJ2FjdGl2ZScpO1xuICAgIH1cbiAgfVxuXG4gIHdyaXRlVmFsdWUodmFsdWU6IGFueSk6IHZvaWQge1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsKSB7XG4gICAgICB0aGlzLnYgPSB2YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52ID0gJyc7XG4gICAgfVxuXG4gICAgdGhpcy5yLnNldFByb3BlcnR5KHRoaXMuaW5wdXRWYWx1ZS5uYXRpdmVFbGVtZW50LCAnaW5uZXJIVE1MJywgdW53cmFwSHRtbEZvclNpbmsoY3JlYXRlSHRtbCh0aGlzLnYpKSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWRcbiAgICogd2hlbiB0aGUgY29udHJvbCByZWNlaXZlcyBhIGNoYW5nZSBldmVudC5cbiAgICpcbiAgICogQHBhcmFtIGZuIGEgZnVuY3Rpb25cbiAgICovXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xuICAgIC8vIHRoaXMub25TdWdnZXN0aW9uU2VsZWN0ZWQgPSBmbjtcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG4gICAqIHdoZW4gdGhlIGNvbnRyb2wgcmVjZWl2ZXMgYSB0b3VjaCBldmVudC5cbiAgICpcbiAgICogQHBhcmFtIGZuIGEgZnVuY3Rpb25cbiAgICovXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgZGlzYWJsZWQgc3RhdGUgZm9yIHRoaXMgZWxlbWVudFxuICAgKlxuICAgKiBAcGFyYW0gaXNEaXNhYmxlZCBEaXNhYmxlZCBzdGF0ZSBmbGFnXG4gICAqL1xuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImF1dG9jb21wbGV0ZVwiPlxuICA8aW5wdXQgW2Rpc2FibGVkXT1cImRpc2FibGVkICA/IHRydWUgOiBudWxsXCIgdHlwZT1cInRleHRcIiBjbGFzcz1cInNlYXJjaFwiICNpbnB1dFZhbHVlIChpbnB1dCk9XCJnZXREYXRhKGlucHV0VmFsdWUudmFsdWUpXCJcbiAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiIChrZXl1cC5BcnJvd0Rvd24pPVwib25BcnJvd0Rvd24oKVwiIChrZXl1cC5BcnJvd1VwKT1cIm9uQXJyb3dVcCgpXCJcbiAgICAgICAgIChrZXl1cC5FbnRlcik9XCJvbkVudGVyKCRldmVudClcIiBzcGVsbGNoZWNrPVwiZmFsc2VcIiBbKG5nTW9kZWwpXT1cInZhbHVlXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCIgLz5cbiAgPGRpdiAqbmdJZj1cImRhdGEubGVuZ3RoXCI+XG4gICAgPGRpdiBjbGFzcz1cImF1dG9jb21wbGV0ZS1pdGVtc1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImF1dG9jb21wbGVsZS1pdGVtXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZGF0YTsgbGV0IGkgPSBpbmRleFwiIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgaXRlbSlcIiBbaWRdPVwiaSsnaXRlbSdcIj5cbiAgICAgICAge3tpdGVtLnZhbHVlfX1cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInR5cGU9PT0ncGFydHknXCI+XG4gICAgICAgICAgPGJyLz5cbiAgICAgICAgICA8c3Bhbj57e2l0ZW0uZGF0YT8uaW5ufX0ge3tjb25maWcucGFydHlBZGRyZXNzID09PSAnZnVsbCcgPyBpdGVtLmRhdGE/LmFkZHJlc3M/LnZhbHVlIDogaXRlbS5kYXRhPy5hZGRyZXNzPy5kYXRhPy5jaXR5fX08L3NwYW4+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==