angular-bootstrap-datetimepicker
Version:
Native Angular (8+) datetime picker component styled by Twitter Bootstrap 4.
516 lines • 53.9 kB
JavaScript
/**
* @license
* Copyright 2013-present Dale Lotts All Rights Reserved.
* http://www.dalelotts.com
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/dalelotts/angular-bootstrap-datetimepicker/blob/master/LICENSE
*/
var DlDateTimePickerComponent_1;
import * as tslib_1 from "tslib";
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, NgZone, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import * as _moment from 'moment';
import { take } from 'rxjs/operators';
import { DlDateAdapter } from '../core/public-api';
import { DlDateTimePickerChange } from './dl-date-time-picker-change';
import { DlDayModelProvider } from './dl-model-provider-day';
import { DlHourModelProvider } from './dl-model-provider-hour';
import { DlMinuteModelProvider } from './dl-model-provider-minute';
import { DlMonthModelProvider } from './dl-model-provider-month';
import { DlYearModelProvider } from './dl-model-provider-year';
/**
* Work around for moment namespace conflict when used with webpack and rollup.
* See https://github.com/dherges/ng-packagr/issues/163
*
* Depending on whether rollup is used, moment needs to be imported differently.
* Since Moment.js doesn't have a default export, we normally need to import using
* the `* as`syntax.
*
* rollup creates a synthetic default module and we thus need to import it using
* the `default as` syntax.
*
* @internal
**/
const moment = _moment;
/**
* Maps key codes to the model provider function name
* that should be called to perform the action.
*
* @internal
**/
const keyCodeToModelProviderMethod = {
'ArrowDown': 'goDown',
'ArrowLeft': 'goLeft',
'ArrowRight': 'goRight',
'ArrowUp': 'goUp',
'Down': 'goDown',
'End': 'goEnd',
'Home': 'goHome',
'Left': 'goLeft',
'PageDown': 'pageDown',
'PageUp': 'pageUp',
'Right': 'goRight',
'Up': 'goUp',
33: 'pageUp',
34: 'pageDown',
35: 'goEnd',
36: 'goHome',
37: 'goLeft',
38: 'goUp',
39: 'goRight',
40: 'goDown',
};
/**
* List of view names for the calendar.
*
* This list must be in order from
* smallest increment of time to largest increment of time.
*
* @internal
**/
const VIEWS = [
'minute',
'hour',
'day',
'month',
'year'
];
/**
* Component that provides all of the user facing functionality of the date/time picker.
*/
let DlDateTimePickerComponent = DlDateTimePickerComponent_1 = class DlDateTimePickerComponent {
/**
* Used to construct a new instance of a date/time picker.
*
* @param _elementRef
* reference to this element.
* @param _ngZone
* reference to an NgZone instance used to select the active element outside of angular.
* @param _dateAdapter
* date adapter for the date type in the model.
* @param yearModelComponent
* provider for the year view model.
* @param monthModelComponent
* provider for the month view model.
* @param dayModelComponent
* provider for the day view model.
* @param hourModelComponent
* provider for the hour view model.
* @param minuteModelComponent
* provider for the minute view model.
*/
constructor(_elementRef, _ngZone, _dateAdapter,
// @ts-ignore
yearModelComponent,
// @ts-ignore
monthModelComponent,
// @ts-ignore
dayModelComponent,
// @ts-ignore
hourModelComponent,
// @ts-ignore
minuteModelComponent) {
this._elementRef = _elementRef;
this._ngZone = _ngZone;
this._dateAdapter = _dateAdapter;
this.yearModelComponent = yearModelComponent;
this.monthModelComponent = monthModelComponent;
this.dayModelComponent = dayModelComponent;
this.hourModelComponent = hourModelComponent;
this.minuteModelComponent = minuteModelComponent;
/**
* Change listener callback functions registered
* via `registerOnChange`
* @internal
**/
this._changed = [];
/**
* Maps view name to the next view (the view for the next smallest increment of time).
* @internal
**/
this._nextView = {
'year': 'month',
'month': 'day',
'day': 'hour',
'hour': 'minute'
};
/**
* Maps view name to the previous view (the view for the next largest increment of time).
* @internal
**/
this._previousView = {
'minute': 'hour',
'hour': 'day',
'day': 'month',
'month': 'year'
};
/**
* Touch listener callback functions registered
* via `registerOnChange`
* @internal
**/
this._touched = [];
/**
* Emits when a `change` event when date/time is selected or
* the value of the date/time picker changes.
**/
this.change = new EventEmitter();
/**
* Specifies the classes used to display the left icon.
*
* This component uses OPENICONIC https://useiconic.com/open
* by default but any icon library may be used.
*/
this.leftIconClass = [
'oi',
'oi-chevron-left'
];
/**
* The highest view that the date/time picker can show.
* Setting this to a view less than year could make it more
* difficult for the end-user to navigate to certain dates.
*/
this.maxView = 'year';
/**
* The view that will be used for date/time selection.
*
* The default of `minute means that selection will not happen
* until the end-user clicks on a cell in the minute view.
*
* for example, if you want the end-user to select a only day (date),
* setting `minView` to `day` will cause selection to happen when the
* end-user selects a cell in the day view.
*
* NOTE: This must be set lower than or equal to `startView'
*/
this.minView = 'minute';
/**
* The number of minutes between each `.dl-abdtp-minute` button.
*
* Must be greater than `0` and less than `60`.
*/
this.minuteStep = 5;
/**
* Specifies the classes used to display the right icon.
*
* This component uses OPENICONIC https://useiconic.com/open
* by default but any icon library may be used.
*/
this.rightIconClass = [
'oi',
'oi-chevron-right'
];
/* tslint:disable:member-ordering */
/**
* Determine whether or not the `DateButton` is selectable by the end user.
*/
this.selectFilter = () => true;
/**
* The initial view that the date/time picker will show.
* The picker will also return to this view after a date/time
* is selected.
*
* NOTE: This must be set lower than or equal to `maxView'
*/
this.startView = 'day';
/**
* Specifies the classes used to display the up icon.
*
* This component uses OPENICONIC https://useiconic.com/open
* by default but any icon library may be used.
*/
this.upIconClass = [
'oi',
'oi-chevron-top'
];
this._viewToModelProvider = {
year: yearModelComponent,
month: monthModelComponent,
day: dayModelComponent,
hour: hourModelComponent,
minute: minuteModelComponent,
};
}
/* tslint:enable:member-ordering */
/**
* Set's the model for the current view after applying the selection filter.
*
* @internal
**/
set model(model) {
this._model = this.applySelectFilter(model);
}
/**
* Returns `D` value of the date/time picker or undefined/null if no value is set.
**/
get value() {
return this._value;
}
/**
* Sets value of the date/time picker and emits a change event if the
* new value is different from the previous value.
**/
set value(value) {
if (this._value !== value) {
this._value = value;
this.model = this._viewToModelProvider[this._model.viewName].getModel(this.getStartDate(), this.valueOf);
this._changed.forEach(f => f(value));
this.change.emit(new DlDateTimePickerChange(value));
}
}
/**
* Returns `milliseconds` value of the date/time picker or undefined/null if no value is set.
**/
get valueOf() {
return this._dateAdapter.toMilliseconds(this._value);
}
/**
* Applies the `selectionFilter` by adding the `dl-abdtp-disabled`
* class to any `DateButton` where `selectFilter` returned false.
*
* @param model
* the new model
*
* @returns
* the supplied model with zero or more `DateButton`'s
* having the `dl-abdtp-disabled` class set to `true` if the
* selection for that date should be disabled.
*
* @internal
*/
applySelectFilter(model) {
if (this.selectFilter) {
model.rows = model.rows.map((row) => {
row.cells.map((dateButton) => {
const disabled = !this.selectFilter(dateButton, model.viewName);
dateButton.classes['dl-abdtp-disabled'] = disabled;
if (disabled) {
dateButton.classes['aria-disabled'] = true;
}
return dateButton;
});
return row;
});
}
return model;
}
/**
* Focuses the `.dl-abdtp-active` cell after the microtask queue is empty.
* @internal
**/
focusActiveCell() {
this._ngZone.runOutsideAngular(() => {
this._ngZone.onStable.asObservable().pipe(take(1)).subscribe(() => {
this._elementRef.nativeElement.querySelector('.dl-abdtp-active').focus();
});
});
}
/**
* Determines the start date for the picker.
* @internal
**/
getStartDate() {
if (hasValue(this._value)) {
return this._dateAdapter.toMilliseconds(this._value);
}
if (hasValue(this.startDate)) {
return this.startDate;
}
return moment().valueOf();
}
/**
* Determine the start view for the picker
* @returns
* the largest time increment view between the `minView` or `minute` view and the `startView` or `day` view.
*/
getStartView() {
const startIndex = Math.max(VIEWS.indexOf(this.minView || 'minute'), VIEWS.indexOf(this.startView || 'day'));
return VIEWS[startIndex];
}
/**
* Calls all registered `touch` callback functions.
* @internal
**/
onTouch() {
this._touched.forEach((onTouched) => onTouched());
}
/**
* Receives configuration changes detected by Angular and passes the changes on
* to the model providers so the provider is aware of any necessary configuration
* changes (i.e. minuteStep)
*
* @param changes
* the input changes detected by Angular.
*/
ngOnChanges(changes) {
Object.values(this._viewToModelProvider).forEach((provider) => provider.onChanges(changes));
if (this._model) { // only update the model after ngOnInit has set it the first time.
this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.activeDate, this.valueOf);
}
}
/**
* Sets the initial model.
*
* @internal
**/
ngOnInit() {
this.model = this._viewToModelProvider[this.getStartView()].getModel(this.getStartDate(), this.valueOf);
}
/**
* Handles click (and enter & space key down) events on the date elements.
*
* If the current view is the minimum view then the date value is selected
* and the picker returns to the start view.
*
* Otherwise the picker displays the next view with the next
* smallest time increment.
*
* @internal
**/
_onDateClick(dateButton) {
if (dateButton.classes['dl-abdtp-disabled']) {
return;
}
let nextView = this._nextView[this._model.viewName];
if ((this.minView || 'minute') === this._model.viewName) {
this.value = this._dateAdapter.fromMilliseconds(dateButton.value);
nextView = this.startView;
}
this.model = this._viewToModelProvider[nextView].getModel(dateButton.value, this.valueOf);
this.onTouch();
}
/**
* Handles click (and enter & space key down) events on the left button.
*
* Changes the displayed time range of the picker to the previous time range.
* For example, in year view, the previous decade is displayed.
*
* @internal
**/
_onLeftClick() {
this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.leftButton.value, this.valueOf);
this.onTouch();
}
/**
* Handles click (and enter & space key down) events on the up button.
*
* Changes the view of the picker to the next largest time increment.
* For example, in day view, the next view displayed will be month view.
*
* @internal
**/
_onUpClick() {
this.model = this._viewToModelProvider[this._previousView[this._model.viewName]].getModel(this._model.upButton.value, this.valueOf);
}
/**
* Handles click (and enter & space key down) events on the right button.
*
* Changes the displayed time range of the picker to the next time range.
* For example, in year view, the next decade is displayed.
*
* @internal
**/
_onRightClick() {
this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.rightButton.value, this.valueOf);
this.onTouch();
}
/**
* Handles various key down events to move the `active date` around the calendar.
*
* @internal
**/
_handleKeyDown($event) {
const functionName = keyCodeToModelProviderMethod[$event.key];
if (functionName) {
const modelProvider = this._viewToModelProvider[this._model.viewName];
this.model = modelProvider[functionName](this._model.activeDate, this.valueOf);
this.focusActiveCell();
// Prevent unexpected default actions such as form submission.
$event.preventDefault();
}
}
/**
* Implements ControlValueAccessor.registerOnChange to register change listeners.
* @internal
**/
registerOnChange(fn) {
this._changed.push(fn);
}
/**
* Implements ControlValueAccessor.registerOnTouched to register touch listeners.
* @internal
**/
registerOnTouched(fn) {
this._touched.push(fn);
}
/**
* Implements ControlValueAccessor.writeValue to store the value from the model.
* @internal
**/
writeValue(value) {
this.value = value;
}
};
DlDateTimePickerComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: NgZone },
{ type: DlDateAdapter },
{ type: DlYearModelProvider },
{ type: DlMonthModelProvider },
{ type: DlDayModelProvider },
{ type: DlHourModelProvider },
{ type: DlMinuteModelProvider }
];
tslib_1.__decorate([
Output()
], DlDateTimePickerComponent.prototype, "change", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "leftIconClass", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "maxView", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "minView", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "minuteStep", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "rightIconClass", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "selectFilter", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "startDate", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "startView", void 0);
tslib_1.__decorate([
Input()
], DlDateTimePickerComponent.prototype, "upIconClass", void 0);
DlDateTimePickerComponent = DlDateTimePickerComponent_1 = tslib_1.__decorate([
Component({
changeDetection: ChangeDetectionStrategy.OnPush,
preserveWhitespaces: false,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: DlDateTimePickerComponent_1,
multi: true
}
],
selector: 'dl-date-time-picker',
template: "<div class=\"text-center dl-abdtp-{{_model.viewName}}-view\" [attr.data-dl-abdtp-view]=\"_model.viewName\">\n <div class=\"row align-items-center no-gutters\">\n <button class=\"col dl-abdtp-left-button align-items-center\"\n type=\"button\"\n [attr.aria-label]=\"_model.leftButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.leftButton.value\"\n [attr.title]=\"_model.leftButton.ariaLabel\"\n (click)=\"_onLeftClick()\"\n ><span class=\"left-icon\" [ngClass]=\"leftIconClass\"></span>\n </button>\n\n <div *ngIf=\"_model.viewName === (this.maxView || 'year'); then maxViewLabel else defaultViewLabel;\"></div>\n\n <button class=\"col dl-abdtp-right-button\"\n type=\"button\"\n [attr.aria-label]=\"_model.rightButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.rightButton.value\"\n [attr.title]=\"_model.rightButton.ariaLabel\"\n (click)=\"_onRightClick()\"\n ><span class=\"right-icon\" [ngClass]=\"rightIconClass\"></span>\n </button>\n </div>\n <div (keydown)=\"_handleKeyDown($event)\">\n <div *ngIf=\"_model.rowLabels?.length\" class=\"row no-gutters\">\n <div *ngFor=\"let label of _model.rowLabels\"\n class=\"col align-items-center no-gutters dl-abdtp-col-label\">{{label}}</div>\n </div>\n <div *ngFor=\"let row of _model.rows\" class=\"row align-items-center no-gutters\">\n <div *ngFor=\"let cell of row.cells\"\n role=\"gridcell\"\n class=\"col dl-abdtp-date-button dl-abdtp-{{_model.viewName}}\"\n [ngClass]=\"cell.classes\"\n [attr.aria-label]=\"cell.ariaLabel\"\n [attr.aria-disabled]=\"cell.classes['dl-abdtp-disabled']\"\n [attr.dl-abdtp-value]=\"cell.value\"\n [attr.tabindex]=\"cell.classes['dl-abdtp-active'] ? 0 : -1\"\n (click)=\"_onDateClick(cell)\"\n (keydown.space)=\"_onDateClick(cell)\"\n (keydown.enter)=\"_onDateClick(cell)\"\n >{{cell.display}}</div>\n </div>\n </div>\n</div>\n\n<ng-template #maxViewLabel>\n <div class=\"col-10 dl-abdtp-view-label\">{{_model.viewLabel}}</div>\n</ng-template>\n<ng-template #defaultViewLabel>\n <button class=\"col-10 dl-abdtp-view-label dl-abdtp-up-button\"\n type=\"button\"\n [attr.aria-label]=\"_model.upButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.upButton.value\"\n [attr.title]=\"_model.upButton.ariaLabel\"\n (click)=\"_onUpClick()\"\n [ngClass]=\"_model.upButton.classes\"\n >{{_model.viewLabel}} <span class=\"up-icon\" [ngClass]=\"upIconClass\"></span>\n </button>\n</ng-template>\n",
styles: [":host{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dl-abdtp-col-label,.dl-abdtp-view-label{font-weight:700}.dl-abdtp-date-button,.dl-abdtp-left-button,.dl-abdtp-right-button,.dl-abdtp-view-label{padding:5px;border-radius:999px;cursor:pointer;color:rgba(0,0,0,.87);outline:0}.dl-abdtp-date-button,.dl-abdtp-left-button,.dl-abdtp-right-button,.dl-abdtp-up-button{border-width:0}.dl-abdtp-active:focus,.dl-abdtp-date-button:focus,.dl-abdtp-date-button:hover,.dl-abdtp-left-button:focus,.dl-abdtp-left-button:hover,.dl-abdtp-right-button:focus,.dl-abdtp-right-button:hover,.dl-abdtp-up-button:focus,.dl-abdtp-up-button:hover,.dl-abdtp-view-label:focus{background:rgba(0,0,0,.04)}.dl-abdtp-future,.dl-abdtp-past{color:rgba(0,0,0,.04)}.dl-abdtp-now,.dl-abdtp-now.disabled,.dl-abdtp-now.disabled:hover,.dl-abdtp-now:hover{border-radius:999px;border:1px solid rgba(0,0,0,.25)}.dl-abdtp-selected{color:#fff;background:rgba(0,82,204,.75)}.dl-abdtp-selected:focus,.dl-abdtp-selected:hover{background:#0052cc}.dl-abdtp-disabled{cursor:default;color:rgba(0,0,0,.25)}"]
})
], DlDateTimePickerComponent);
export { DlDateTimePickerComponent };
/** @internal */
function hasValue(value) {
return (typeof value !== 'undefined') && (value !== null);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGwtZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9hbmd1bGFyLWJvb3RzdHJhcC1kYXRldGltZXBpY2tlci8iLCJzb3VyY2VzIjpbImRsLWRhdGUtdGltZS1waWNrZXIvZGwtZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRzs7O0FBRUgsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLFNBQVMsRUFDVCxNQUFNLEVBQ04sTUFBTSxFQUNOLGFBQWEsRUFDZCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQXVCLGlCQUFpQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkUsT0FBTyxLQUFLLE9BQU8sTUFBTSxRQUFRLENBQUM7QUFDbEMsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3BDLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUNqRCxPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSw4QkFBOEIsQ0FBQztBQUlwRSxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRCxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUNqRSxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUMvRCxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUU3RDs7Ozs7Ozs7Ozs7O0lBWUk7QUFDSixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUM7QUFHdkI7Ozs7O0lBS0k7QUFFSixNQUFNLDRCQUE0QixHQUFHO0lBQ25DLFdBQVcsRUFBRSxRQUFRO0lB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QUNoQixTQUFTLFFBQVEsQ0FBQyxLQUFVO0lBQzFCLE9BQU8sQ0FBQyxPQUFPLEtBQUssS0FBSyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQztBQUM1RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTMtcHJlc2VudCBEYWxlIExvdHRzIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBodHRwOi8vd3d3LmRhbGVsb3R0cy5jb21cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2dpdGh1Yi5jb20vZGFsZWxvdHRzL2FuZ3VsYXItYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyL2Jsb2IvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuXG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uQ2hhbmdlcyxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXNcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7Q29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgKiBhcyBfbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQge3Rha2V9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7RGxEYXRlQWRhcHRlcn0gZnJvbSAnLi4vY29yZS9wdWJsaWMtYXBpJztcbmltcG9ydCB7RGxEYXRlVGltZVBpY2tlckNoYW5nZX0gZnJvbSAnLi9kbC1kYXRlLXRpbWUtcGlja2VyLWNoYW5nZSc7XG5pbXBvcnQge0RhdGVCdXR0b259IGZyb20gJy4vZGwtZGF0ZS10aW1lLXBpY2tlci1kYXRlLWJ1dHRvbic7XG5pbXBvcnQge0RsRGF0ZVRpbWVQaWNrZXJNb2RlbH0gZnJvbSAnLi9kbC1kYXRlLXRpbWUtcGlja2VyLW1vZGVsJztcbmltcG9ydCB7RGxNb2RlbFByb3ZpZGVyfSBmcm9tICcuL2RsLW1vZGVsLXByb3ZpZGVyJztcbmltcG9ydCB7RGxEYXlNb2RlbFByb3ZpZGVyfSBmcm9tICcuL2RsLW1vZGVsLXByb3ZpZGVyLWRheSc7XG5pbXBvcnQge0RsSG91ck1vZGVsUHJvdmlkZXJ9IGZyb20gJy4vZGwtbW9kZWwtcHJvdmlkZXItaG91cic7XG5pbXBvcnQge0RsTWludXRlTW9kZWxQcm92aWRlcn0gZnJvbSAnLi9kbC1tb2RlbC1wcm92aWRlci1taW51dGUnO1xuaW1wb3J0IHtEbE1vbnRoTW9kZWxQcm92aWRlcn0gZnJvbSAnLi9kbC1tb2RlbC1wcm92aWRlci1tb250aCc7XG5pbXBvcnQge0RsWWVhck1vZGVsUHJvdmlkZXJ9IGZyb20gJy4vZGwtbW9kZWwtcHJvdmlkZXIteWVhcic7XG5cbi8qKlxuICogV29yayBhcm91bmQgZm9yIG1vbWVudCBuYW1lc3BhY2UgY29uZmxpY3Qgd2hlbiB1c2VkIHdpdGggd2VicGFjayBhbmQgcm9sbHVwLlxuICogU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9kaGVyZ2VzL25nLXBhY2thZ3IvaXNzdWVzLzE2M1xuICpcbiAqIERlcGVuZGluZyBvbiB3aGV0aGVyIHJvbGx1cCBpcyB1c2VkLCBtb21lbnQgbmVlZHMgdG8gYmUgaW1wb3J0ZWQgZGlmZmVyZW50bHkuXG4gKiBTaW5jZSBNb21lbnQuanMgZG9lc24ndCBoYXZlIGEgZGVmYXVsdCBleHBvcnQsIHdlIG5vcm1hbGx5IG5lZWQgdG8gaW1wb3J0IHVzaW5nXG4gKiB0aGUgYCogYXNgc3ludGF4LlxuICpcbiAqIHJvbGx1cCBjcmVhdGVzIGEgc3ludGhldGljIGRlZmF1bHQgbW9kdWxlIGFuZCB3ZSB0aHVzIG5lZWQgdG8gaW1wb3J0IGl0IHVzaW5nXG4gKiB0aGUgYGRlZmF1bHQgYXNgIHN5bnRheC5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqKi9cbmNvbnN0IG1vbWVudCA9IF9tb21lbnQ7XG5cblxuLyoqXG4gKiBNYXBzIGtleSBjb2RlcyB0byB0aGUgbW9kZWwgcHJvdmlkZXIgZnVuY3Rpb24gbmFtZVxuICogdGhhdCBzaG91bGQgYmUgY2FsbGVkIHRvIHBlcmZvcm0gdGhlIGFjdGlvbi5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqKi9cblxuY29uc3Qga2V5Q29kZVRvTW9kZWxQcm92aWRlck1ldGhvZCA9IHtcbiAgJ0Fycm93RG93bic6ICdnb0Rvd24nLFxuICAnQXJyb3dMZWZ0JzogJ2dvTGVmdCcsXG4gICdBcnJvd1JpZ2h0JzogJ2dvUmlnaHQnLFxuICAnQXJyb3dVcCc6ICdnb1VwJyxcbiAgJ0Rvd24nOiAnZ29Eb3duJyxcbiAgJ0VuZCc6ICdnb0VuZCcsXG4gICdIb21lJzogJ2dvSG9tZScsXG4gICdMZWZ0JzogJ2dvTGVmdCcsXG4gICdQYWdlRG93bic6ICdwYWdlRG93bicsXG4gICdQYWdlVXAnOiAncGFnZVVwJyxcbiAgJ1JpZ2h0JzogJ2dvUmlnaHQnLFxuICAnVXAnOiAnZ29VcCcsXG4gIDMzOiAncGFnZVVwJyxcbiAgMzQ6ICdwYWdlRG93bicsXG4gIDM1OiAnZ29FbmQnLFxuICAzNjogJ2dvSG9tZScsXG4gIDM3OiAnZ29MZWZ0JyxcbiAgMzg6ICdnb1VwJyxcbiAgMzk6ICdnb1JpZ2h0JyxcbiAgNDA6ICdnb0Rvd24nLFxufTtcblxuXG4vKipcbiAqIExpc3Qgb2YgdmlldyBuYW1lcyBmb3IgdGhlIGNhbGVuZGFyLlxuICpcbiAqIFRoaXMgbGlzdCBtdXN0IGJlIGluIG9yZGVyIGZyb21cbiAqIHNtYWxsZXN0IGluY3JlbWVudCBvZiB0aW1lIHRvIGxhcmdlc3QgaW5jcmVtZW50IG9mIHRpbWUuXG4gKlxuICogQGludGVybmFsXG4gKiovXG5jb25zdCBWSUVXUyA9IFtcbiAgJ21pbnV0ZScsXG4gICdob3VyJyxcbiAgJ2RheScsXG4gICdtb250aCcsXG4gICd5ZWFyJ1xuXTtcblxuLyoqXG4gKiBDb21wb25lbnQgdGhhdCBwcm92aWRlcyBhbGwgb2YgdGhlIHVzZXIgZmFjaW5nIGZ1bmN0aW9uYWxpdHkgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIuXG4gKi9cblxuQENvbXBvbmVudCh7XG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBwcmVzZXJ2ZVdoaXRlc3BhY2VzOiBmYWxzZSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogRGxEYXRlVGltZVBpY2tlckNvbXBvbmVudCxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdLFxuICBzZWxlY3RvcjogJ2RsLWRhdGUtdGltZS1waWNrZXInLFxuICBzdHlsZVVybHM6IFsnLi9kbC1kYXRlLXRpbWUtcGlja2VyLmNvbXBvbmVudC5zY3NzJ10sXG4gIHRlbXBsYXRlVXJsOiAnLi9kbC1kYXRlLXRpbWUtcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbn0pXG5leHBvcnQgY2xhc3MgRGxEYXRlVGltZVBpY2tlckNvbXBvbmVudDxEPiBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cbiAgLyoqXG4gICAqIENoYW5nZSBsaXN0ZW5lciBjYWxsYmFjayBmdW5jdGlvbnMgcmVnaXN0ZXJlZFxuICAgKiB2aWEgYHJlZ2lzdGVyT25DaGFuZ2VgXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIHByaXZhdGUgX2NoYW5nZWQ6ICgodmFsdWU6IEQpID0+IHZvaWQpW10gPSBbXTtcbiAgLyoqXG4gICAqIE1vZGVsIGZvciB0aGUgY3VycmVudCB2aWV3LlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBfbW9kZWw6IERsRGF0ZVRpbWVQaWNrZXJNb2RlbDtcbiAgLyoqXG4gICAqIE1hcHMgdmlldyBuYW1lIHRvIHRoZSBuZXh0IHZpZXcgKHRoZSB2aWV3IGZvciB0aGUgbmV4dCBzbWFsbGVzdCBpbmNyZW1lbnQgb2YgdGltZSkuXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIHByaXZhdGUgX25leHRWaWV3ID0ge1xuICAgICd5ZWFyJzogJ21vbnRoJyxcbiAgICAnbW9udGgnOiAnZGF5JyxcbiAgICAnZGF5JzogJ2hvdXInLFxuICAgICdob3VyJzogJ21pbnV0ZSdcbiAgfTtcbiAgLyoqXG4gICAqIE1hcHMgdmlldyBuYW1lIHRvIHRoZSBwcmV2aW91cyB2aWV3ICh0aGUgdmlldyBmb3IgdGhlIG5leHQgbGFyZ2VzdCBpbmNyZW1lbnQgb2YgdGltZSkuXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIHByaXZhdGUgX3ByZXZpb3VzVmlldyA9IHtcbiAgICAnbWludXRlJzogJ2hvdXInLFxuICAgICdob3VyJzogJ2RheScsXG4gICAgJ2RheSc6ICdtb250aCcsXG4gICAgJ21vbnRoJzogJ3llYXInXG4gIH07XG4gIC8qKlxuICAgKiBUb3VjaCBsaXN0ZW5lciBjYWxsYmFjayBmdW5jdGlvbnMgcmVnaXN0ZXJlZFxuICAgKiB2aWEgYHJlZ2lzdGVyT25DaGFuZ2VgXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIHByaXZhdGUgX3RvdWNoZWQ6ICgoKSA9PiB2b2lkKVtdID0gW107XG4gIC8qKlxuICAgKiBTdG9yZXMgdGhlIHNlbGVjdGVkIHZhbHVlIGZvciB0aGlzIHBpY2tlci5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfdmFsdWU6IEQ7XG4gIC8qKlxuICAgKiBNYXBzIHZpZXcgbmFtZSB0byB0aGUgbW9kZWwgcHJvdmlkZXIgZm9yIHRoYXQgdmlldy5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfdmlld1RvTW9kZWxQcm92aWRlcjoge1xuICAgIHllYXI6IERsTW9kZWxQcm92aWRlcjtcbiAgICBtb250aDogRGxNb2RlbFByb3ZpZGVyO1xuICAgIGRheTogRGxNb2RlbFByb3ZpZGVyO1xuICAgIGhvdXI6IERsTW9kZWxQcm92aWRlcjtcbiAgICBtaW51dGU6IERsTW9kZWxQcm92aWRlcjtcbiAgfTtcbiAgLyoqXG4gICAqIEVtaXRzIHdoZW4gYSBgY2hhbmdlYCBldmVudCB3aGVuIGRhdGUvdGltZSBpcyBzZWxlY3RlZCBvclxuICAgKiB0aGUgdmFsdWUgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIgY2hhbmdlcy5cbiAgICoqL1xuICBAT3V0cHV0KClcbiAgcmVhZG9ubHkgY2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEbERhdGVUaW1lUGlja2VyQ2hhbmdlPEQ+PigpO1xuICAvKipcbiAgICogU3BlY2lmaWVzIHRoZSBjbGFzc2VzIHVzZWQgdG8gZGlzcGxheSB0aGUgbGVmdCBpY29uLlxuICAgKlxuICAgKiBUaGlzIGNvbXBvbmVudCB1c2VzIE9QRU5JQ09OSUMgaHR0cHM6Ly91c2VpY29uaWMuY29tL29wZW5cbiAgICogYnkgZGVmYXVsdCBidXQgYW55IGljb24gbGlicmFyeSBtYXkgYmUgdXNlZC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGxlZnRJY29uQ2xhc3M6IHN0cmluZyB8IHN0cmluZ1tdIHwgU2V0PHN0cmluZz4gfCB7fSA9IFtcbiAgICAnb2knLFxuICAgICdvaS1jaGV2cm9uLWxlZnQnXG4gIF07XG4gIC8qKlxuICAgKiBUaGUgaGlnaGVzdCB2aWV3IHRoYXQgdGhlIGRhdGUvdGltZSBwaWNrZXIgY2FuIHNob3cuXG4gICAqIFNldHRpbmcgdGhpcyB0byBhIHZpZXcgbGVzcyB0aGFuIHllYXIgY291bGQgbWFrZSBpdCBtb3JlXG4gICAqIGRpZmZpY3VsdCBmb3IgdGhlIGVuZC11c2VyIHRvIG5hdmlnYXRlIHRvIGNlcnRhaW4gZGF0ZXMuXG4gICAqL1xuICBASW5wdXQoKVxuICBtYXhWaWV3OiAneWVhcicgfCAnbW9udGgnIHwgJ2RheScgfCAnaG91cicgfCAnbWludXRlJyA9ICd5ZWFyJztcbiAgLyoqXG4gICAqIFRoZSB2aWV3IHRoYXQgd2lsbCBiZSB1c2VkIGZvciBkYXRlL3RpbWUgc2VsZWN0aW9uLlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCBvZiBgbWludXRlICBtZWFucyB0aGF0IHNlbGVjdGlvbiB3aWxsIG5vdCBoYXBwZW5cbiAgICogdW50aWwgdGhlIGVuZC11c2VyIGNsaWNrcyBvbiBhIGNlbGwgaW4gdGhlIG1pbnV0ZSB2aWV3LlxuICAgKlxuICAgKiBmb3IgZXhhbXBsZSwgaWYgeW91IHdhbnQgdGhlIGVuZC11c2VyIHRvIHNlbGVjdCBhIG9ubHkgZGF5IChkYXRlKSxcbiAgICogc2V0dGluZyBgbWluVmlld2AgdG8gYGRheWAgd2lsbCBjYXVzZSBzZWxlY3Rpb24gdG8gaGFwcGVuIHdoZW4gdGhlXG4gICAqIGVuZC11c2VyIHNlbGVjdHMgYSBjZWxsIGluIHRoZSBkYXkgdmlldy5cbiAgICpcbiAgICogTk9URTogVGhpcyBtdXN0IGJlIHNldCBsb3dlciB0aGFuIG9yIGVxdWFsIHRvIGBzdGFydFZpZXcnXG4gICAqL1xuICBASW5wdXQoKVxuICBtaW5WaWV3OiAneWVhcicgfCAnbW9udGgnIHwgJ2RheScgfCAnaG91cicgfCAnbWludXRlJyA9ICdtaW51dGUnO1xuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBtaW51dGVzIGJldHdlZW4gZWFjaCBgLmRsLWFiZHRwLW1pbnV0ZWAgYnV0dG9uLlxuICAgKlxuICAgKiBNdXN0IGJlIGdyZWF0ZXIgdGhhbiBgMGAgYW5kIGxlc3MgdGhhbiBgNjBgLlxuICAgKi9cbiAgQElucHV0KClcbiAgbWludXRlU3RlcCA9IDU7XG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIGNsYXNzZXMgdXNlZCB0byBkaXNwbGF5IHRoZSByaWdodCBpY29uLlxuICAgKlxuICAgKiBUaGlzIGNvbXBvbmVudCB1c2VzIE9QRU5JQ09OSUMgaHR0cHM6Ly91c2VpY29uaWMuY29tL29wZW5cbiAgICogYnkgZGVmYXVsdCBidXQgYW55IGljb24gbGlicmFyeSBtYXkgYmUgdXNlZC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHJpZ2h0SWNvbkNsYXNzID0gW1xuICAgICdvaScsXG4gICAgJ29pLWNoZXZyb24tcmlnaHQnXG4gIF07XG5cbiAgLyogdHNsaW50OmRpc2FibGU6bWVtYmVyLW9yZGVyaW5nICovXG4gIC8qKlxuICAgKiAgRGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IHRoZSBgRGF0ZUJ1dHRvbmAgaXMgc2VsZWN0YWJsZSBieSB0aGUgZW5kIHVzZXIuXG4gICAqL1xuICBASW5wdXQoKVxuICBzZWxlY3RGaWx0ZXI6IChkYXRlQnV0dG9uOiBEYXRlQnV0dG9uLCB2aWV3TmFtZTogc3RyaW5nKSA9PiBib29sZWFuID0gKCkgPT4gdHJ1ZVxuXG4gIC8qKlxuICAgKiAgU3RhcnQgYXQgdGhlIHZpZXcgY29udGFpbmluZyBzdGFydERhdGUgd2hlbiBubyB2YWx1ZSBpcyBzZWxlY3RlZC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHN0YXJ0RGF0ZTogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgaW5pdGlhbCB2aWV3IHRoYXQgdGhlIGRhdGUvdGltZSBwaWNrZXIgd2lsbCBzaG93LlxuICAgKiBUaGUgcGlja2VyIHdpbGwgYWxzbyByZXR1cm4gdG8gdGhpcyB2aWV3IGFmdGVyIGEgZGF0ZS90aW1lXG4gICAqIGlzIHNlbGVjdGVkLlxuICAgKlxuICAgKiBOT1RFOiBUaGlzIG11c3QgYmUgc2V0IGxvd2VyIHRoYW4gb3IgZXF1YWwgdG8gYG1heFZpZXcnXG4gICAqL1xuICBASW5wdXQoKVxuICBzdGFydFZpZXc6ICd5ZWFyJyB8ICdtb250aCcgfCAnZGF5JyB8ICdob3VyJyB8ICdtaW51dGUnID0gJ2RheSc7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgY2xhc3NlcyB1c2VkIHRvIGRpc3BsYXkgdGhlIHVwIGljb24uXG4gICAqXG4gICAqIFRoaXMgY29tcG9uZW50IHVzZXMgT1BFTklDT05JQyBodHRwczovL3VzZWljb25pYy5jb20vb3BlblxuICAgKiBieSBkZWZhdWx0IGJ1dCBhbnkgaWNvbiBsaWJyYXJ5IG1heSBiZSB1c2VkLlxuICAgKi9cbiAgQElucHV0KClcbiAgdXBJY29uQ2xhc3MgPSBbXG4gICAgJ29pJyxcbiAgICAnb2ktY2hldnJvbi10b3AnXG4gIF07XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gY29uc3RydWN0IGEgbmV3IGluc3RhbmNlIG9mIGEgZGF0ZS90aW1lIHBpY2tlci5cbiAgICpcbiAgICogQHBhcmFtIF9lbGVtZW50UmVmXG4gICAqICByZWZlcmVuY2UgdG8gdGhpcyBlbGVtZW50LlxuICAgKiBAcGFyYW0gX25nWm9uZVxuICAgKiAgcmVmZXJlbmNlIHRvIGFuIE5nWm9uZSBpbnN0YW5jZSB1c2VkIHRvIHNlbGVjdCB0aGUgYWN0aXZlIGVsZW1lbnQgb3V0c2lkZSBvZiBhbmd1bGFyLlxuICAgKiBAcGFyYW0gX2RhdGVBZGFwdGVyXG4gICAqICBkYXRlIGFkYXB0ZXIgZm9yIHRoZSBkYXRlIHR5cGUgaW4gdGhlIG1vZGVsLlxuICAgKiBAcGFyYW0geWVhck1vZGVsQ29tcG9uZW50XG4gICAqICBwcm92aWRlciBmb3IgdGhlIHllYXIgdmlldyBtb2RlbC5cbiAgICogQHBhcmFtIG1vbnRoTW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgbW9udGggdmlldyBtb2RlbC5cbiAgICogQHBhcmFtIGRheU1vZGVsQ29tcG9uZW50XG4gICAqICBwcm92aWRlciBmb3IgdGhlIGRheSB2aWV3IG1vZGVsLlxuICAgKiBAcGFyYW0gaG91ck1vZGVsQ29tcG9uZW50XG4gICAqICBwcm92aWRlciBmb3IgdGhlIGhvdXIgdmlldyBtb2RlbC5cbiAgICogQHBhcmFtIG1pbnV0ZU1vZGVsQ29tcG9uZW50XG4gICAqICBwcm92aWRlciBmb3IgdGhlIG1pbnV0ZSB2aWV3IG1vZGVsLlxuICAgKi9cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUsXG4gICAgICAgICAgICAgIHByaXZhdGUgX2RhdGVBZGFwdGVyOiBEbERhdGVBZGFwdGVyPEQ+LFxuICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgIHByaXZhdGUgeWVhck1vZGVsQ29tcG9uZW50OiBEbFllYXJNb2RlbFByb3ZpZGVyLFxuICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgIHByaXZhdGUgbW9udGhNb2RlbENvbXBvbmVudDogRGxNb250aE1vZGVsUHJvdmlkZXIsXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSBkYXlNb2RlbENvbXBvbmVudDogRGxEYXlNb2RlbFByb3ZpZGVyLFxuICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgIHByaXZhdGUgaG91ck1vZGVsQ29tcG9uZW50OiBEbEhvdXJNb2RlbFByb3ZpZGVyLFxuICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgIHByaXZhdGUgbWludXRlTW9kZWxDb21wb25lbnQ6IERsTWludXRlTW9kZWxQcm92aWRlcikge1xuXG4gICAgdGhpcy5fdmlld1RvTW9kZWxQcm92aWRlciA9IHtcbiAgICAgIHllYXI6IHllYXJNb2RlbENvbXBvbmVudCxcbiAgICAgIG1vbnRoOiBtb250aE1vZGVsQ29tcG9uZW50LFxuICAgICAgZGF5OiBkYXlNb2RlbENvbXBvbmVudCxcbiAgICAgIGhvdXI6IGhvdXJNb2RlbENvbXBvbmVudCxcbiAgICAgIG1pbnV0ZTogbWludXRlTW9kZWxDb21wb25lbnQsXG4gICAgfTtcbiAgfVxuXG4gIC8qIHRzbGludDplbmFibGU6bWVtYmVyLW9yZGVyaW5nICovXG4gIC8qKlxuICAgKiBTZXQncyB0aGUgbW9kZWwgZm9yIHRoZSBjdXJyZW50IHZpZXcgYWZ0ZXIgYXBwbHlpbmcgdGhlIHNlbGVjdGlvbiBmaWx0ZXIuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIHByaXZhdGUgc2V0IG1vZGVsKG1vZGVsOiBEbERhdGVUaW1lUGlja2VyTW9kZWwpIHtcbiAgICB0aGlzLl9tb2RlbCA9IHRoaXMuYXBwbHlTZWxlY3RGaWx0ZXIobW9kZWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYERgIHZhbHVlIG9mIHRoZSBkYXRlL3RpbWUgcGlja2VyIG9yIHVuZGVmaW5lZC9udWxsIGlmIG5vIHZhbHVlIGlzIHNldC5cbiAgICoqL1xuICBnZXQgdmFsdWUoKTogRCB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdmFsdWUgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIgYW5kIGVtaXRzIGEgY2hhbmdlIGV2ZW50IGlmIHRoZVxuICAgKiBuZXcgdmFsdWUgaXMgZGlmZmVyZW50IGZyb20gdGhlIHByZXZpb3VzIHZhbHVlLlxuICAgKiovXG4gIHNldCB2YWx1ZSh2YWx1ZTogRCkge1xuICAgIGlmICh0aGlzLl92YWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XG4gICAgICB0aGlzLm1vZGVsID0gdGhpcy5fdmlld1RvTW9kZWxQcm92aWRlclt0aGlzLl9tb2RlbC52aWV3TmFtZV0uZ2V0TW9kZWwodGhpcy5nZXRTdGFydERhdGUoKSwgdGhpcy52YWx1ZU9mKTtcbiAgICAgIHRoaXMuX2NoYW5nZWQuZm9yRWFjaChmID0+IGYodmFsdWUpKTtcbiAgICAgIHRoaXMuY2hhbmdlLmVtaXQobmV3IERsRGF0ZVRpbWVQaWNrZXJDaGFuZ2U8RD4odmFsdWUpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBgbWlsbGlzZWNvbmRzYCB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlciBvciB1bmRlZmluZWQvbnVsbCBpZiBubyB2YWx1ZSBpcyBzZXQuXG4gICAqKi9cbiAgZ2V0IHZhbHVlT2YoKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGVBZGFwdGVyLnRvTWlsbGlzZWNvbmRzKHRoaXMuX3ZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIHRoZSBgc2VsZWN0aW9uRmlsdGVyYCBieSBhZGRpbmcgdGhlIGBkbC1hYmR0cC1kaXNhYmxlZGBcbiAgICogY2xhc3MgdG8gYW55IGBEYXRlQnV0dG9uYCB3aGVyZSBgc2VsZWN0RmlsdGVyYCByZXR1cm5lZCBmYWxzZS5cbiAgICpcbiAgICogQHBhcmFtIG1vZGVsXG4gICAqICB0aGUgbmV3IG1vZGVsXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqICB0aGUgc3VwcGxpZWQgbW9kZWwgd2l0aCB6ZXJvIG9yIG1vcmUgYERhdGVCdXR0b25gJ3NcbiAgICogIGhhdmluZyB0aGUgYGRsLWFiZHRwLWRpc2FibGVkYCBjbGFzcyBzZXQgdG8gYHRydWVgIGlmIHRoZVxuICAgKiAgc2VsZWN0aW9uIGZvciB0aGF0IGRhdGUgc2hvdWxkIGJlIGRpc2FibGVkLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByaXZhdGUgYXBwbHlTZWxlY3RGaWx0ZXIobW9kZWw6IERsRGF0ZVRpbWVQaWNrZXJNb2RlbCk6IERsRGF0ZVRpbWVQaWNrZXJNb2RlbCB7XG4gICAgaWYgKHRoaXMuc2VsZWN0RmlsdGVyKSB7XG4gICAgICBtb2RlbC5yb3dzID0gbW9kZWwucm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3cuY2VsbHMubWFwKChkYXRlQnV0dG9uOiBEYXRlQnV0dG9uKSA9PiB7XG4gICAgICAgICAgY29uc3QgZGlzYWJsZWQgPSAhdGhpcy5zZWxlY3RGaWx0ZXIoZGF0ZUJ1dHRvbiwgbW9kZWwudmlld05hbWUpO1xuICAgICAgICAgIGRhdGVCdXR0b24uY2xhc3Nlc1snZGwtYWJkdHAtZGlzYWJsZWQnXSA9IGRpc2FibGVkO1xuICAgICAgICAgIGlmIChkaXNhYmxlZCkge1xuICAgICAgICAgICAgZGF0ZUJ1dHRvbi5jbGFzc2VzWydhcmlhLWRpc2FibGVkJ10gPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZGF0ZUJ1dHRvbjtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByb3c7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogRm9jdXNlcyB0aGUgYC5kbC1hYmR0cC1hY3RpdmVgIGNlbGwgYWZ0ZXIgdGhlIG1pY3JvdGFzayBxdWV1ZSBpcyBlbXB0eS5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBmb2N1c0FjdGl2ZUNlbGwoKSB7XG4gICAgdGhpcy5fbmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIHRoaXMuX25nWm9uZS5vblN0YWJsZS5hc09ic2VydmFibGUoKS5waXBlKHRha2UoMSkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuZGwtYWJkdHAtYWN0aXZlJykuZm9jdXMoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgdGhlIHN0YXJ0IGRhdGUgZm9yIHRoZSBwaWNrZXIuXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIHByaXZhdGUgZ2V0U3RhcnREYXRlKCkge1xuICAgIGlmIChoYXNWYWx1ZSh0aGlzLl92YWx1ZSkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9kYXRlQWRhcHRlci50b01pbGxpc2Vjb25kcyh0aGlzLl92YWx1ZSk7XG4gICAgfVxuICAgIGlmIChoYXNWYWx1ZSh0aGlzLnN0YXJ0RGF0ZSkpIHtcbiAgICAgIHJldHVybiB0aGlzLnN0YXJ0RGF0ZTtcbiAgICB9XG4gICAgcmV0dXJuIG1vbWVudCgpLnZhbHVlT2YoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgdGhlIHN0YXJ0IHZpZXcgZm9yIHRoZSBwaWNrZXJcbiAgICogQHJldHVybnNcbiAgICogIHRoZSBsYXJnZXN0IHRpbWUgaW5jcmVtZW50IHZpZXcgYmV0d2VlbiB0aGUgYG1pblZpZXdgIG9yIGBtaW51dGVgIHZpZXcgYW5kIHRoZSBgc3RhcnRWaWV3YCBvciBgZGF5YCB2aWV3LlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRTdGFydFZpZXcoKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdGFydEluZGV4ID0gTWF0aC5tYXgoVklFV1MuaW5kZXhPZih0aGlzLm1pblZpZXcgfHwgJ21pbnV0ZScpLCBWSUVXUy5pbmRleE9mKHRoaXMuc3RhcnRWaWV3IHx8ICdkYXknKSk7XG4gICAgcmV0dXJuIFZJRVdTW3N0YXJ0SW5kZXhdO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxzIGFsbCByZWdpc3RlcmVkIGB0b3VjaGAgY2FsbGJhY2sgZnVuY3Rpb25zLlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBwcml2YXRlIG9uVG91Y2goKSB7XG4gICAgdGhpcy5fdG91Y2hlZC5mb3JFYWNoKChvblRvdWNoZWQpID0+IG9uVG91Y2hlZCgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNlaXZlcyBjb25maWd1cmF0aW9uIGNoYW5nZXMgZGV0ZWN0ZWQgYnkgQW5ndWxhciBhbmQgcGFzc2VzIHRoZSBjaGFuZ2VzIG9uXG4gICAqIHRvIHRoZSBtb2RlbCBwcm92aWRlcnMgc28gdGhlIHByb3ZpZGVyIGlzIGF3YXJlIG9mIGFueSBuZWNlc3NhcnkgY29uZmlndXJhdGlvblxuICAgKiBjaGFuZ2VzIChpLmUuIG1pbnV0ZVN0ZXApXG4gICAqXG4gICAqIEBwYXJhbSBjaGFuZ2VzXG4gICAqICB0aGUgaW5wdXQgY2hhbmdlcyBkZXRlY3RlZCBieSBBbmd1bGFyLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIE9iamVjdC52YWx1ZXModGhpcy5fdmlld1RvTW9kZWxQcm92aWRlcikuZm9yRWFjaCgocHJvdmlkZXI6IERsTW9kZWxQcm92aWRlcikgPT4gcHJvdmlkZXIub25DaGFuZ2VzKGNoYW5nZXMpKTtcblxuICAgIGlmICh0aGlzLl9tb2RlbCkgeyAvLyBvbmx5IHVwZGF0ZSB0aGUgbW9kZWwgYWZ0ZXIgbmdPbkluaXQgaGFzIHNldCBpdCB0aGUgZmlyc3QgdGltZS5cbiAgICAgIHRoaXMubW9kZWwgPSB0aGlzLl92aWV3VG9Nb2RlbFByb3ZpZGVyW3RoaXMuX21vZGVsLnZpZXdOYW1lXS5nZXRNb2RlbCh0aGlzLl9tb2RlbC5hY3RpdmVEYXRlLCB0aGlzLnZhbHVlT2YpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBpbml0aWFsIG1vZGVsLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm1vZGVsID0gdGhpcy5fdmlld1RvTW9kZWxQcm92aWRlclt0aGlzLmdldFN0YXJ0VmlldygpXS5nZXRNb2RlbCh0aGlzLmdldFN0YXJ0RGF0ZSgpLCB0aGlzLnZhbHVlT2YpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgY2xpY2sgKGFuZCBlbnRlciAmIHNwYWNlIGtleSBkb3duKSBldmVudHMgb24gdGhlIGRhdGUgZWxlbWVudHMuXG4gICAqXG4gICAqIElmIHRoZSBjdXJyZW50IHZpZXcgaXMgdGhlIG1pbmltdW0gdmlldyB0aGVuIHRoZSBkYXRlIHZhbHVlIGlzIHNlbGVjdGVkXG4gICAqIGFuZCB0aGUgcGlja2VyIHJldHVybnMgdG8gdGhlIHN0YXJ0IHZpZXcuXG4gICAqXG4gICAqIE90aGVyd2lzZSB0aGUgcGlja2VyIGRpc3BsYXlzIHRoZSBuZXh0IHZpZXcgd2l0aCB0aGUgbmV4dFxuICAgKiBzbWFsbGVzdCB0aW1lIGluY3JlbWVudC5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgX29uRGF0ZUNsaWNrKGRhdGVCdXR0b246IERhdGVCdXR0b24pIHtcbiAgICBpZiAoZGF0ZUJ1dHRvbi5jbGFzc2VzWydkbC1hYmR0cC1kaXNhYmxlZCddKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IG5leHRWaWV3ID0gdG