UNPKG

@clr/angular

Version:

Angular components for Clarity

290 lines 39 kB
/* * Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ import { isPlatformBrowser } from '@angular/common'; import { Directive, EventEmitter, HostBinding, HostListener, Inject, Input, Optional, Output, PLATFORM_ID, Self, } from '@angular/core'; import { of } from 'rxjs'; import { filter, switchMap } from 'rxjs/operators'; import { isBooleanAttributeSet } from '../../utils/component/is-boolean-attribute-set'; import { WrappedFormControl } from '../common/wrapped-control'; import { ClrDateContainer } from './date-container'; import { DayModel } from './model/day.model'; import { DateFormControlService } from './providers/date-form-control.service'; import { DateIOService } from './providers/date-io.service'; import { DateNavigationService } from './providers/date-navigation.service'; import { DatepickerEnabledService } from './providers/datepicker-enabled.service'; import { DatepickerFocusService } from './providers/datepicker-focus.service'; import { datesAreEqual } from './utils/date-utils'; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "./date-container"; import * as i3 from "./providers/date-io.service"; import * as i4 from "./providers/date-navigation.service"; import * as i5 from "./providers/datepicker-enabled.service"; import * as i6 from "./providers/date-form-control.service"; import * as i7 from "../common/providers/focus.service"; import * as i8 from "./providers/datepicker-focus.service"; // There are four ways the datepicker value is set // 1. Value set by user typing into text input as a string ex: '01/28/2015' // 2. Value set explicitly by Angular Forms APIs as a string ex: '01/28/2015' // 3. Value set by user via datepicker UI as a Date Object // 4. Value set via `clrDate` input as a Date Object export class ClrDateInput extends WrappedFormControl { constructor(viewContainerRef, injector, el, renderer, control, container, dateIOService, dateNavigationService, datepickerEnabledService, dateFormControlService, platformId, focusService, datepickerFocusService) { super(viewContainerRef, ClrDateContainer, injector, control, renderer, el); this.el = el; this.renderer = renderer; this.control = control; this.container = container; this.dateIOService = dateIOService; this.dateNavigationService = dateNavigationService; this.datepickerEnabledService = datepickerEnabledService; this.dateFormControlService = dateFormControlService; this.platformId = platformId; this.focusService = focusService; this.datepickerFocusService = datepickerFocusService; this.dateChange = new EventEmitter(false); this.index = 1; } set date(date) { if (this.previousDateChange !== date) { this.updateDate(this.getValidDateValueFromDate(date)); } if (!this.initialClrDateInputValue) { this.initialClrDateInputValue = date; } } set min(dateString) { this.dateIOService.setMinDate(dateString); } set max(dateString) { this.dateIOService.setMaxDate(dateString); } get disabled() { if (this.dateFormControlService) { return this.dateFormControlService.disabled; } return null; } set disabled(value) { if (this.dateFormControlService) { this.dateFormControlService.setDisabled(isBooleanAttributeSet(value)); } } get placeholderText() { return this.placeholder ? this.placeholder : this.dateIOService.placeholderText; } get inputType() { return isPlatformBrowser(this.platformId) && this.usingNativeDatepicker() ? 'date' : 'text'; } ngOnInit() { super.ngOnInit(); this.populateServicesFromContainerComponent(); this.subscriptions.push(this.listenForUserSelectedDayChanges(), this.listenForControlValueChanges(), this.listenForTouchChanges(), this.listenForDirtyChanges(), this.listenForInputRefocus()); } ngAfterViewInit() { // I don't know why I have to do this but after using the new HostWrapping Module I have to delay the processing // of the initial Input set by the user to here. If I do not 2 issues occur: // 1. The Input setter is called before ngOnInit. ngOnInit initializes the services without which the setter fails. // 2. The Renderer doesn't work before ngAfterViewInit (It used to before the new HostWrapping Module for some reason). // I need the renderer to set the value property on the input to make sure that if the user has supplied a Date // input object, we reflect it with the right date on the input field using the IO service. I am not sure if // these are major issues or not but just noting them down here. this.processInitialInputs(); } setFocusStates() { this.setFocus(true); } triggerValidation() { super.triggerValidation(); this.setFocus(false); } onValueChange(target) { const validDateValue = this.dateIOService.getDateValueFromDateString(target.value); if (this.usingClarityDatepicker() && validDateValue) { this.updateDate(validDateValue, true); } else if (this.usingNativeDatepicker()) { const [year, month, day] = target.value.split('-'); this.updateDate(new Date(+year, +month - 1, +day), true); } else { this.emitDateOutput(null); } } usingClarityDatepicker() { return this.datepickerEnabledService.isEnabled; } usingNativeDatepicker() { return !this.datepickerEnabledService.isEnabled; } setFocus(focus) { if (this.focusService) { this.focusService.focused = focus; } } populateServicesFromContainerComponent() { if (!this.container) { this.dateIOService = this.getProviderFromContainer(DateIOService); this.dateNavigationService = this.getProviderFromContainer(DateNavigationService); this.datepickerEnabledService = this.getProviderFromContainer(DatepickerEnabledService); this.dateFormControlService = this.getProviderFromContainer(DateFormControlService); } } processInitialInputs() { if (this.datepickerHasFormControl()) { this.updateDate(this.dateIOService.getDateValueFromDateString(this.control.value)); } else { this.updateDate(this.initialClrDateInputValue); } } updateDate(value, setByUserInteraction = false) { const date = this.getValidDateValueFromDate(value); if (setByUserInteraction) { this.emitDateOutput(date); } else { this.previousDateChange = date; } if (this.dateNavigationService) { this.dateNavigationService.selectedDay = date ? new DayModel(date.getFullYear(), date.getMonth(), date.getDate()) : null; } this.updateInput(date); } updateInput(date) { if (date) { const dateString = this.dateIOService.toLocaleDisplayFormatString(date); if (this.usingNativeDatepicker()) { // valueAsDate expects UTC, date from input is time-zoned date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); this.renderer.setProperty(this.el.nativeElement, 'valueAsDate', date); } else if (this.datepickerHasFormControl() && dateString !== this.control.value) { this.control.control.setValue(dateString); } else { this.renderer.setProperty(this.el.nativeElement, 'value', dateString); } } else { this.renderer.setProperty(this.el.nativeElement, 'value', ''); } } getValidDateValueFromDate(date) { if (this.dateIOService) { const dateString = this.dateIOService.toLocaleDisplayFormatString(date); return this.dateIOService.getDateValueFromDateString(dateString); } else { return null; } } emitDateOutput(date) { if (!datesAreEqual(date, this.previousDateChange)) { this.dateChange.emit(date); this.previousDateChange = date; } else if (!date && this.previousDateChange) { this.dateChange.emit(null); this.previousDateChange = null; } } datepickerHasFormControl() { return !!this.control; } listenForControlValueChanges() { return of(this.datepickerHasFormControl()) .pipe(filter(hasControl => hasControl), switchMap(() => this.control.valueChanges), // only update date value if not being set by user filter(() => !this.datepickerFocusService.elementIsFocused(this.el.nativeElement))) .subscribe((value) => this.updateDate(this.dateIOService.getDateValueFromDateString(value))); } listenForUserSelectedDayChanges() { return this.dateNavigationService.selectedDayChange.subscribe(dayModel => this.updateDate(dayModel.toDate(), true)); } listenForTouchChanges() { return this.dateFormControlService.touchedChange .pipe(filter(() => this.datepickerHasFormControl())) .subscribe(() => this.control.control.markAsTouched()); } listenForDirtyChanges() { return this.dateFormControlService.dirtyChange .pipe(filter(() => this.datepickerHasFormControl())) .subscribe(() => this.control.control.markAsDirty()); } listenForInputRefocus() { return this.dateNavigationService.selectedDayChange .pipe(filter(date => !!date)) .subscribe(() => this.datepickerFocusService.focusInput(this.el.nativeElement)); } } ClrDateInput.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrDateInput, deps: [{ token: i0.ViewContainerRef }, { token: i0.Injector }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.NgControl, optional: true, self: true }, { token: i2.ClrDateContainer, optional: true }, { token: i3.DateIOService, optional: true }, { token: i4.DateNavigationService, optional: true }, { token: i5.DatepickerEnabledService, optional: true }, { token: i6.DateFormControlService, optional: true }, { token: PLATFORM_ID }, { token: i7.FocusService, optional: true }, { token: i8.DatepickerFocusService }], target: i0.ɵɵFactoryTarget.Directive }); ClrDateInput.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: ClrDateInput, selector: "[clrDate]", inputs: { placeholder: "placeholder", date: ["clrDate", "date"], min: "min", max: "max", disabled: "disabled" }, outputs: { dateChange: "clrDateChange" }, host: { listeners: { "focus": "setFocusStates()", "blur": "triggerValidation()", "change": "onValueChange($event.target)" }, properties: { "class.clr-input": "true", "disabled": "this.disabled", "attr.placeholder": "this.placeholderText", "attr.type": "this.inputType" } }, providers: [DatepickerFocusService], usesInheritance: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrDateInput, decorators: [{ type: Directive, args: [{ selector: '[clrDate]', host: { '[class.clr-input]': 'true', }, providers: [DatepickerFocusService], }] }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.Injector }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.NgControl, decorators: [{ type: Self }, { type: Optional }] }, { type: i2.ClrDateContainer, decorators: [{ type: Optional }] }, { type: i3.DateIOService, decorators: [{ type: Optional }] }, { type: i4.DateNavigationService, decorators: [{ type: Optional }] }, { type: i5.DatepickerEnabledService, decorators: [{ type: Optional }] }, { type: i6.DateFormControlService, decorators: [{ type: Optional }] }, { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }, { type: i7.FocusService, decorators: [{ type: Optional }] }, { type: i8.DatepickerFocusService }]; }, propDecorators: { placeholder: [{ type: Input }], dateChange: [{ type: Output, args: ['clrDateChange'] }], date: [{ type: Input, args: ['clrDate'] }], min: [{ type: Input }], max: [{ type: Input }], disabled: [{ type: Input, args: ['disabled'] }, { type: HostBinding, args: ['disabled'] }], placeholderText: [{ type: HostBinding, args: ['attr.placeholder'] }], inputType: [{ type: HostBinding, args: ['attr.type'] }], setFocusStates: [{ type: HostListener, args: ['focus'] }], triggerValidation: [{ type: HostListener, args: ['blur'] }], onValueChange: [{ type: HostListener, args: ['change', ['$event.target']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1pbnB1dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXIvc3JjL2Zvcm1zL2RhdGVwaWNrZXIvZGF0ZS1pbnB1dC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBRUgsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDcEQsT0FBTyxFQUVMLFNBQVMsRUFFVCxZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixNQUFNLEVBRU4sS0FBSyxFQUdMLFFBQVEsRUFDUixNQUFNLEVBQ04sV0FBVyxFQUVYLElBQUksR0FFTCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzFCLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbkQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sZ0RBQWdELENBQUM7QUFFdkYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDL0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDcEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQy9FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM1RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUNsRixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUM5RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7Ozs7Ozs7Ozs7QUFFbkQsa0RB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UztzQkFEWixXQUFXO3VCQUFDLFdBQVc7Z0JBOEJ4QixjQUFjO3NCQURiLFlBQVk7dUJBQUMsT0FBTztnQkFNWixpQkFBaUI7c0JBRHpCLFlBQVk7dUJBQUMsTUFBTTtnQkFPcEIsYUFBYTtzQkFEWixZQUFZO3VCQUFDLFFBQVEsRUFBRSxDQUFDLGVBQWUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTYtMjAyMyBWTXdhcmUsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIFRoaXMgc29mdHdhcmUgaXMgcmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UuXG4gKiBUaGUgZnVsbCBsaWNlbnNlIGluZm9ybWF0aW9uIGNhbiBiZSBmb3VuZCBpbiBMSUNFTlNFIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHByb2plY3QuXG4gKi9cblxuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RCaW5kaW5nLFxuICBIb3N0TGlzdGVuZXIsXG4gIEluamVjdCxcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgUExBVEZPUk1fSUQsXG4gIFJlbmRlcmVyMixcbiAgU2VsZixcbiAgVmlld0NvbnRhaW5lclJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ0NvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IGlzQm9vbGVhbkF0dHJpYnV0ZVNldCB9IGZyb20gJy4uLy4uL3V0aWxzL2NvbXBvbmVudC9pcy1ib29sZWFuLWF0dHJpYnV0ZS1zZXQnO1xuaW1wb3J0IHsgRm9jdXNTZXJ2aWNlIH0gZnJvbSAnLi4vY29tbW9uL3Byb3ZpZGVycy9mb2N1cy5zZXJ2aWNlJztcbmltcG9ydCB7IFdyYXBwZWRGb3JtQ29udHJvbCB9IGZyb20gJy4uL2NvbW1vbi93cmFwcGVkLWNvbnRyb2wnO1xuaW1wb3J0IHsgQ2xyRGF0ZUNvbnRhaW5lciB9IGZyb20gJy4vZGF0ZS1jb250YWluZXInO1xuaW1wb3J0IHsgRGF5TW9kZWwgfSBmcm9tICcuL21vZGVsL2RheS5tb2RlbCc7XG5pbXBvcnQgeyBEYXRlRm9ybUNvbnRyb2xTZXJ2aWNlIH0gZnJvbSAnLi9wcm92aWRlcnMvZGF0ZS1mb3JtLWNvbnRyb2wuc2VydmljZSc7XG5pbXBvcnQgeyBEYXRlSU9TZXJ2aWNlIH0gZnJvbSAnLi9wcm92aWRlcnMvZGF0ZS1pby5zZXJ2aWNlJztcbmltcG9ydCB7IERhdGVOYXZpZ2F0aW9uU2VydmljZSB9IGZyb20gJy4vcHJvdmlkZXJzL2RhdGUtbmF2aWdhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IERhdGVwaWNrZXJFbmFibGVkU2VydmljZSB9IGZyb20gJy4vcHJvdmlkZXJzL2RhdGVwaWNrZXItZW5hYmxlZC5zZXJ2aWNlJztcbmltcG9ydCB7IERhdGVwaWNrZXJGb2N1c1NlcnZpY2UgfSBmcm9tICcuL3Byb3ZpZGVycy9kYXRlcGlja2VyLWZvY3VzLnNlcnZpY2UnO1xuaW1wb3J0IHsgZGF0ZXNBcmVFcXVhbCB9IGZyb20gJy4vdXRpbHMvZGF0ZS11dGlscyc7XG5cbi8vIFRoZXJlIGFyZSBmb3VyIHdheXMgdGhlIGRhdGVwaWNrZXIgdmFsdWUgaXMgc2V0XG4vLyAxLiBWYWx1ZSBzZXQgYnkgdXNlciB0eXBpbmcgaW50byB0ZXh0IGlucHV0IGFzIGEgc3RyaW5nIGV4OiAnMDEvMjgvMjAxNSdcbi8vIDIuIFZhbHVlIHNldCBleHBsaWNpdGx5IGJ5IEFuZ3VsYXIgRm9ybXMgQVBJcyBhcyBhIHN0cmluZyBleDogJzAxLzI4LzIwMTUnXG4vLyAzLiBWYWx1ZSBzZXQgYnkgdXNlciB2aWEgZGF0ZXBpY2tlciBVSSBhcyBhIERhdGUgT2JqZWN0XG4vLyA0LiBWYWx1ZSBzZXQgdmlhIGBjbHJEYXRlYCBpbnB1dCBhcyBhIERhdGUgT2JqZWN0XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tjbHJEYXRlXScsXG4gIGhvc3Q6IHtcbiAgICAnW2NsYXNzLmNsci1pbnB1dF0nOiAndHJ1ZScsXG4gIH0sXG4gIHByb3ZpZGVyczogW0RhdGVwaWNrZXJGb2N1c1NlcnZpY2VdLFxufSlcbmV4cG9ydCBjbGFzcyBDbHJEYXRlSW5wdXQgZXh0ZW5kcyBXcmFwcGVkRm9ybUNvbnRyb2w8Q2xyRGF0ZUNvbnRhaW5lcj4gaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9kYXRlOiBEYXRlIHwgbnVsbCB8IHN0cmluZztcblxuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nO1xuICBAT3V0cHV0KCdjbHJEYXRlQ2hhbmdlJykgZGF0ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0ZT4oZmFsc2UpO1xuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBpbmRleCA9IDE7XG5cbiAgcHJpdmF0ZSBpbml0aWFsQ2xyRGF0ZUlucHV0VmFsdWU6IERhdGU7XG4gIHByaXZhdGUgcHJldmlvdXNEYXRlQ2hhbmdlOiBEYXRlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYsXG4gICAgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByb3RlY3RlZCBvdmVycmlkZSBlbDogRWxlbWVudFJlZixcbiAgICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgICBAU2VsZigpXG4gICAgQE9wdGlvbmFsKClcbiAgICBwcm90ZWN0ZWQgY29udHJvbDogTmdDb250cm9sLFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgY29udGFpbmVyOiBDbHJEYXRlQ29udGFpbmVyLFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgZGF0ZUlPU2VydmljZTogRGF0ZUlPU2VydmljZSxcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIGRhdGVOYXZpZ2F0aW9uU2VydmljZTogRGF0ZU5hdmlnYXRpb25TZXJ2aWNlLFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgZGF0ZXBpY2tlckVuYWJsZWRTZXJ2aWNlOiBEYXRlcGlja2VyRW5hYmxlZFNlcnZpY2UsXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBkYXRlRm9ybUNvbnRyb2xTZXJ2aWNlOiBEYXRlRm9ybUNvbnRyb2xTZXJ2aWNlLFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgcGxhdGZvcm1JZDogYW55LFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgZm9jdXNTZXJ2aWNlOiBGb2N1c1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBkYXRlcGlja2VyRm9jdXNTZXJ2aWNlOiBEYXRlcGlja2VyRm9jdXNTZXJ2aWNlXG4gICkge1xuICAgIHN1cGVyKHZpZXdDb250YWluZXJSZWYsIENsckRhdGVDb250YWluZXIsIGluamVjdG9yLCBjb250cm9sLCByZW5kZXJlciwgZWwpO1xuICB9XG5cbiAgQElucHV0KCdjbHJEYXRlJylcbiAgc2V0IGRhdGUoZGF0ZTogRGF0ZSB8IHN0cmluZykge1xuICAgIGlmICh0aGlzLnByZXZpb3VzRGF0ZUNoYW5nZSAhPT0gZGF0ZSkge1xuICAgICAgdGhpcy51cGRhdGVEYXRlKHRoaXMuZ2V0VmFsaWREYXRlVmFsdWVGcm9tRGF0ZShkYXRlIGFzIERhdGUpKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaW5pdGlhbENsckRhdGVJbnB1dFZhbHVlKSB7XG4gICAgICB0aGlzLmluaXRpYWxDbHJEYXRlSW5wdXRWYWx1ZSA9IGRhdGUgYXMgRGF0ZTtcbiAgICB9XG4gIH1cblxuICBASW5wdXQoKVxuICBzZXQgbWluKGRhdGVTdHJpbmc6IHN0cmluZykge1xuICAgIHRoaXMuZGF0ZUlPU2VydmljZS5zZXRNaW5EYXRlKGRhdGVTdHJpbmcpO1xuICB9XG5cbiAgQElucHV0KClcbiAgc2V0IG1heChkYXRlU3RyaW5nOiBzdHJpbmcpIHtcbiAgICB0aGlzLmRhdGVJT1NlcnZpY2Uuc2V0TWF4RGF0ZShkYXRlU3RyaW5nKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICBpZiAodGhpcy5kYXRlRm9ybUNvbnRyb2xTZXJ2aWNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5kYXRlRm9ybUNvbnRyb2xTZXJ2aWNlLmRpc2FibGVkO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIEBJbnB1dCgnZGlzYWJsZWQnKVxuICBASG9zdEJpbmRpbmcoJ2Rpc2FibGVkJylcbiAgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuIHwgc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuZGF0ZUZvcm1Db250cm9sU2VydmljZSkge1xuICAgICAgdGhpcy5kYXRlRm9ybUNvbnRyb2xTZXJ2aWNlLnNldERpc2FibGVkKGlzQm9vbGVhbkF0dHJpYnV0ZVNldCh2YWx1ZSkpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0QmluZGluZygnYXR0ci5wbGFjZWhvbGRlcicpXG4gIGdldCBwbGFjZWhvbGRlclRleHQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5wbGFjZWhvbGRlciA/IHRoaXMucGxhY2Vob2xkZXIgOiB0aGlzLmRhdGVJT1NlcnZpY2UucGxhY2Vob2xkZXJUZXh0O1xuICB9XG5cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLnR5cGUnKVxuICBnZXQgaW5wdXRUeXBlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkgJiYgdGhpcy51c2luZ05hdGl2ZURhdGVwaWNrZXIoKSA/ICdkYXRlJyA6ICd0ZXh0JztcbiAgfVxuXG4gIG92ZXJyaWRlIG5nT25Jbml0KCkge1xuICAgIHN1cGVyLm5nT25Jbml0KCk7XG4gICAgdGhpcy5wb3B1bGF0ZVNlcnZpY2VzRnJvbUNvbnRhaW5lckNvbXBvbmVudCgpO1xuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLmxpc3RlbkZvclVzZXJTZWxlY3RlZERheUNoYW5nZXMoKSxcbiAgICAgIHRoaXMubGlzdGVuRm9yQ29udHJvbFZhbHVlQ2hhbmdlcygpLFxuICAgICAgdGhpcy5saXN0ZW5Gb3JUb3VjaENoYW5nZXMoKSxcbiAgICAgIHRoaXMubGlzdGVuRm9yRGlydHlDaGFuZ2VzKCksXG4gICAgICB0aGlzLmxpc3RlbkZvcklucHV0UmVmb2N1cygpXG4gICAgKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICAvLyBJIGRvbid0IGtub3cgd2h5IEkgaGF2ZSB0byBkbyB0aGlzIGJ1dCBhZnRlciB1c2luZyB0aGUgbmV3IEhvc3RXcmFwcGluZyBNb2R1bGUgSSBoYXZlIHRvIGRlbGF5IHRoZSBwcm9jZXNzaW5nXG4gICAgLy8gb2YgdGhlIGluaXRpYWwgSW5wdXQgc2V0IGJ5IHRoZSB1c2VyIHRvIGhlcmUuIElmIEkgZG8gbm90IDIgaXNzdWVzIG9jY3VyOlxuICAgIC8vIDEuIFRoZSBJbnB1dCBzZXR0ZXIgaXMgY2FsbGVkIGJlZm9yZSBuZ09uSW5pdC4gbmdPbkluaXQgaW5pdGlhbGl6ZXMgdGhlIHNlcnZpY2VzIHdpdGhvdXQgd2hpY2ggdGhlIHNldHRlciBmYWlscy5cbiAgICAvLyAyLiBUaGUgUmVuZGVyZXIgZG9lc24ndCB3b3JrIGJlZm9yZSBuZ0FmdGVyVmlld0luaXQgKEl0IHVzZWQgdG8gYmVmb3JlIHRoZSBuZXcgSG9zdFdyYXBwaW5nIE1vZHVsZSBmb3Igc29tZSByZWFzb24pLlxuICAgIC8vIEkgbmVlZCB0aGUgcmVuZGVyZXIgdG8gc2V0IHRoZSB2YWx1ZSBwcm9wZXJ0eSBvbiB0aGUgaW5wdXQgdG8gbWFrZSBzdXJlIHRoYXQgaWYgdGhlIHVzZXIgaGFzIHN1cHBsaWVkIGEgRGF0ZVxuICAgIC8vIGlucHV0IG9iamVjdCwgd2UgcmVmbGVjdCBpdCB3aXRoIHRoZSByaWdodCBkYXRlIG9uIHRoZSBpbnB1dCBmaWVsZCB1c2luZyB0aGUgSU8gc2VydmljZS4gSSBhbSBub3Qgc3VyZSBpZlxuICAgIC8vIHRoZXNlIGFyZSBtYWpvciBpc3N1ZXMgb3Igbm90IGJ1dCBqdXN0IG5vdGluZyB0aGVtIGRvd24gaGVyZS5cbiAgICB0aGlzLnByb2Nlc3NJbml0aWFsSW5wdXRzKCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdmb2N1cycpXG4gIHNldEZvY3VzU3RhdGVzKCkge1xuICAgIHRoaXMuc2V0Rm9jdXModHJ1ZSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdibHVyJylcbiAgb3ZlcnJpZGUgdHJpZ2dlclZhbGlkYXRpb24oKSB7XG4gICAgc3VwZXIudHJpZ2dlclZhbGlkYXRpb24oKTtcbiAgICB0aGlzLnNldEZvY3VzKGZhbHNlKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2NoYW5nZScsIFsnJGV2ZW50LnRhcmdldCddKVxuICBvblZhbHVlQ2hhbmdlKHRhcmdldDogSFRNTElucHV0RWxlbWVudCkge1xuICAgIGNvbnN0IHZhbGlkRGF0ZVZhbHVlID0gdGhpcy5kYXRlSU9TZXJ2aWNlLmdldERhdGVWYWx1ZUZyb21EYXRlU3RyaW5nKHRhcmdldC52YWx1ZSk7XG4gICAgaWYgKHRoaXMudXNpbmdDbGFyaXR5RGF0ZXBpY2tlcigpICYmIHZhbGlkRGF0ZVZhbHVlKSB7XG4gICAgICB0aGlzLnVwZGF0ZURhdGUodmFsaWREYXRlVmFsdWUsIHRydWUpO1xuICAgIH0gZWxzZSBpZiAodGhpcy51c2luZ05hdGl2ZURhdGVwaWNrZXIoKSkge1xuICAgICAgY29uc3QgW3llYXIsIG1vbnRoLCBkYXldID0gdGFyZ2V0LnZhbHVlLnNwbGl0KCctJyk7XG4gICAgICB0aGlzLnVwZGF0ZURhdGUobmV3IERhdGUoK3llYXIsICttb250aCAtIDEsICtkYXkpLCB0cnVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lbWl0RGF0ZU91dHB1dChudWxsKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVzaW5nQ2xhcml0eURhdGVwaWNrZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0ZXBpY2tlckVuYWJsZWRTZXJ2aWNlLmlzRW5hYmxlZDtcbiAgfVxuXG4gIHByaXZhdGUgdXNpbmdOYXRpdmVEYXRlcGlja2VyKCkge1xuICAgIHJldHVybiAhdGhpcy5kYXRlcGlja2VyRW5hYmxlZFNlcnZpY2UuaXNFbmFibGVkO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRGb2N1cyhmb2N1czogYm9vbGVhbikge1xuICAgIGlmICh0aGlzLmZvY3VzU2VydmljZSkge1xuICAgICAgdGhpcy5mb2N1c1NlcnZpY2UuZm9jdXNlZCA9IGZvY3VzO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcG9wdWxhdGVTZXJ2aWNlc0Zyb21Db250YWluZXJDb21wb25lbnQoKSB7XG4gICAgaWYgKCF0aGlzLmNvbnRhaW5lcikge1xuICAgICAgdGhpcy5kYXRlSU9TZXJ2aWNlID0gdGhpcy5nZXRQcm92aWRlckZyb21Db250YWluZXIoRGF0ZUlPU2VydmljZSk7XG4gICAgICB0aGlzLmRhdGVOYXZpZ2F0aW9uU2VydmljZSA9IHRoaXMuZ2V0UHJvdmlkZXJGcm9tQ29udGFpbmVyKERhdGVOYXZpZ2F0aW9uU2VydmljZSk7XG4gICAgICB0aGlzLmRhdGVwaWNrZXJFbmFibGVkU2VydmljZSA9IHRoaXMuZ2V0UHJvdmlkZXJGcm9tQ29udGFpbmVyKERhdGVwaWNrZXJFbmFibGVkU2VydmljZSk7XG4gICAgICB0aGlzLmRhdGVGb3JtQ29udHJvbFNlcnZpY2UgPSB0aGlzLmdldFByb3ZpZGVyRnJvbUNvbnRhaW5lcihEYXRlRm9ybUNvbnRyb2xTZXJ2aWNlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NJbml0aWFsSW5wdXRzKCkge1xuICAgIGlmICh0aGlzLmRhdGVwaWNrZXJIYXNGb3JtQ29udHJvbCgpKSB7XG4gICAgICB0aGlzLnVwZGF0ZURhdGUodGhpcy5kYXRlSU9TZXJ2aWNlLmdldERhdGVWYWx1ZUZyb21EYXRlU3RyaW5nKHRoaXMuY29udHJvbC52YWx1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVwZGF0ZURhdGUodGhpcy5pbml0aWFsQ2xyRGF0ZUlucHV0VmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlRGF0ZSh2YWx1ZTogRGF0ZSwgc2V0QnlVc2VySW50ZXJhY3Rpb24gPSBmYWxzZSkge1xuICAgIGNvbnN0IGRhdGUgPSB0aGlzLmdldFZhbGlkRGF0ZVZhbHVlRnJvbURhdGUodmFsdWUpO1xuXG4gICAgaWYgKHNldEJ5VXNlckludGVyYWN0aW9uKSB7XG4gICAgICB0aGlzLmVtaXREYXRlT3V0cHV0KGRhdGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnByZXZpb3VzRGF0ZUNoYW5nZSA9IGRhdGU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZGF0ZU5hdmlnYXRpb25TZXJ2aWNlKSB7XG4gICAgICB0aGlzLmRhdGVOYXZpZ2F0aW9uU2VydmljZS5zZWxlY3RlZERheSA9IGRhdGVcbiAgICAgICAgPyBuZXcgRGF5TW9kZWwoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RGF0ZSgpKVxuICAgICAgICA6IG51bGw7XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGVJbnB1dChkYXRlKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlSW5wdXQoZGF0ZTogRGF0ZSkge1xuICAgIGlmIChkYXRlKSB7XG4gICAgICBjb25zdCBkYXRlU3RyaW5nID0gdGhpcy5kYXRlSU9TZXJ2aWNlLnRvTG9jYWxlRGlzcGxheUZvcm1hdFN0cmluZyhkYXRlKTtcbiAgICAgIGlmICh0aGlzLnVzaW5nTmF0aXZlRGF0ZXBpY2tlcigpKSB7XG4gICAgICAgIC8vIHZhbHVlQXNEYXRlIGV4cGVjdHMgVVRDLCBkYXRlIGZyb20gaW5wdXQgaXMgdGltZS16b25lZFxuICAgICAgICBkYXRlLnNldE1pbnV0ZXMoZGF0ZS5nZXRNaW51dGVzKCkgLSBkYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkpO1xuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFByb3BlcnR5KHRoaXMuZWwubmF0aXZlRWxlbWVudCwgJ3ZhbHVlQXNEYXRlJywgZGF0ZSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0ZXBpY2tlckhhc0Zvcm1Db250cm9sKCkgJiYgZGF0ZVN0cmluZyAhPT0gdGhpcy5jb250cm9sLnZhbHVlKSB7XG4gICAgICAgIHRoaXMuY29udHJvbC5jb250cm9sLnNldFZhbHVlKGRhdGVTdHJpbmcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5zZXRQcm9wZXJ0eSh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsICd2YWx1ZScsIGRhdGVTdHJpbmcpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnNldFByb3BlcnR5KHRoaXMuZWwubmF0aXZlRWxlbWVudCwgJ3ZhbHVlJywgJycpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0VmFsaWREYXRlVmFsdWVGcm9tRGF0ZShkYXRlOiBEYXRlKSB7XG4gICAgaWYgKHRoaXMuZGF0ZUlPU2VydmljZSkge1xuICAgICAgY29uc3QgZGF0ZVN0cmluZyA9IHRoaXMuZGF0ZUlPU2VydmljZS50b0xvY2FsZURpc3BsYXlGb3JtYXRTdHJpbmcoZGF0ZSk7XG4gICAgICByZXR1cm4gdGhpcy5kYXRlSU9TZXJ2aWNlLmdldERhdGVWYWx1ZUZyb21EYXRlU3RyaW5nKGRhdGVTdHJpbmcpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGVtaXREYXRlT3V0cHV0KGRhdGU6IERhdGUpIHtcbiAgICBpZiAoIWRhdGVzQXJlRXF1YWwoZGF0ZSwgdGhpcy5wcmV2aW91c0RhdGVDaGFuZ2UpKSB7XG4gICAgICB0aGlzLmRhdGVDaGFuZ2UuZW1pdChkYXRlKTtcbiAgICAgIHRoaXMucHJldmlvdXNEYXRlQ2hhbmdlID0gZGF0ZTtcbiAgICB9IGVsc2UgaWYgKCFkYXRlICYmIHRoaXMucHJldmlvdXNEYXRlQ2hhbmdlKSB7XG4gICAgICB0aGlzLmRhdGVDaGFuZ2UuZW1pdChudWxsKTtcbiAgICAgIHRoaXMucHJldmlvdXNEYXRlQ2hhbmdlID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRhdGVwaWNrZXJIYXNGb3JtQ29udHJvbCgpIHtcbiAgICByZXR1cm4gISF0aGlzLmNvbnRyb2w7XG4gIH1cblxuICBwcml2YXRlIGxpc3RlbkZvckNvbnRyb2xWYWx1ZUNoYW5nZXMoKSB7XG4gICAgcmV0dXJuIG9mKHRoaXMuZGF0ZXBpY2tlckhhc0Zvcm1Db250cm9sKCkpXG4gICAgICAucGlwZShcbiAgICAgICAgZmlsdGVyKGhhc0NvbnRyb2wgPT4gaGFzQ29udHJvbCksXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLmNvbnRyb2wudmFsdWVDaGFuZ2VzKSxcbiAgICAgICAgLy8gb25seSB1cGRhdGUgZGF0ZSB2YWx1ZSBpZiBub3QgYmVpbmcgc2V0IGJ5IHVzZXJcbiAgICAgICAgZmlsdGVyKCgpID0+ICF0aGlzLmRhdGVwaWNrZXJGb2N1c1NlcnZpY2UuZWxlbWVudElzRm9jdXNlZCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQpKVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgodmFsdWU6IHN0cmluZykgPT4gdGhpcy51cGRhdGVEYXRlKHRoaXMuZGF0ZUlPU2VydmljZS5nZXREYXRlVmFsdWVGcm9tRGF0ZVN0cmluZyh2YWx1ZSkpKTtcbiAgfVxuXG4gIHByaXZhdGUgbGlzdGVuRm9yVXNlclNlbGVjdGVkRGF5Q2hhbmdlcygpIHtcbiAgICByZXR1cm4gdGhpcy5kYXRlTmF2aWdhdGlvblNlcnZpY2Uuc2VsZWN0ZWREYXlDaGFuZ2Uuc3Vic2NyaWJlKGRheU1vZGVsID0+IHRoaXMudXBkYXRlRGF0ZShkYXlNb2RlbC50b0RhdGUoKSwgdHJ1ZSkpO1xuICB9XG5cbiAgcHJpdmF0ZSBsaXN0ZW5Gb3JUb3VjaENoYW5nZXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0ZUZvcm1Db250cm9sU2VydmljZS50b3VjaGVkQ2hhbmdlXG4gICAgICAucGlwZShmaWx0ZXIoKCkgPT4gdGhpcy5kYXRlcGlja2VySGFzRm9ybUNvbnRyb2woKSkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuY29udHJvbC5jb250cm9sLm1hcmtBc1RvdWNoZWQoKSk7XG4gIH1cblxuICBwcml2YXRlIGxpc3RlbkZvckRpcnR5Q2hhbmdlcygpIHtcbiAgICByZXR1cm4gdGhpcy5kYXRlRm9ybUNvbnRyb2xTZXJ2aWNlLmRpcnR5Q2hhbmdlXG4gICAgICAucGlwZShmaWx0ZXIoKCkgPT4gdGhpcy5kYXRlcGlja2VySGFzRm9ybUNvbnRyb2woKSkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuY29udHJvbC5jb250cm9sLm1hcmtBc0RpcnR5KCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBsaXN0ZW5Gb3JJbnB1dFJlZm9jdXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRGF5Q2hhbmdlXG4gICAgICAucGlwZShmaWx0ZXIoZGF0ZSA9PiAhIWRhdGUpKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmRhdGVwaWNrZXJGb2N1c1NlcnZpY2UuZm9jdXNJbnB1dCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQpKTtcbiAgfVxufVxuIl19