@asoftwareworld/form-builder-pro
Version:
ASW Form Builder Pro helps you with rapid development and designed web forms which includes several controls. The key feature of Form Builder is to make your content attractive and effective. We can customize our control at run time and preview the same b
228 lines • 34.2 kB
JavaScript
import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, Optional, Output, ViewEncapsulation } from '@angular/core';
import { createMissingDateImplError } from '../datetimepicker-errors';
import { AswCalendarCell } from '../calendar-body/calendar-body';
import { aswDatetimepickerAnimations } from '../datetimepicker-animations';
import { ASW_DATETIME_FORMATS } from '@asoftwareworld/form-builder-pro/common';
import * as i0 from "@angular/core";
import * as i1 from "@asoftwareworld/form-builder-pro/common";
import * as i2 from "../calendar-body/calendar-body";
export const yearsPerPage = 24;
export const yearsPerRow = 4;
/**
* An internal component used to display multiple years in the datetimepicker.
* @docs-private
*/
export class AswMultiYearView {
_adapter;
_dateFormats;
type = 'date';
/** A function used to filter which dates are selectable. */
dateFilter;
/** Emits when a new month is selected. */
selectedChange = new EventEmitter();
/** Emits when any date is selected. */
_userSelection = new EventEmitter();
/** Grid of calendar cells representing the years in the range. */
_years;
/** The label for this year range (e.g. "2000-2020"). */
_yearLabel;
/** The year in this range that today falls on. Null if today is in a different range. */
_todayYear;
/**
* The year in this range that the selected Date falls on.
* Null if the selected Date is in a different range.
*/
_selectedYear;
_calendarState;
constructor(_adapter, _dateFormats) {
this._adapter = _adapter;
this._dateFormats = _dateFormats;
if (!this._adapter) {
throw createMissingDateImplError('DatetimeAdapter');
}
if (!this._dateFormats) {
throw createMissingDateImplError('ASW_DATETIME_FORMATS');
}
this._activeDate = this._adapter.today();
}
/** The date to display in this multi year view */
get activeDate() {
return this._activeDate;
}
set activeDate(value) {
const oldActiveDate = this._activeDate;
this._activeDate = value || this._adapter.today();
if (oldActiveDate && this._activeDate && !isSameMultiYearView(this._adapter, oldActiveDate, this._activeDate, this.minDate, this.maxDate)) {
this._init();
}
}
_activeDate;
/** The currently selected date. */
get selected() {
return this._selected;
}
set selected(value) {
this._selected = value;
this._selectedYear = this._selected && this._adapter.getYear(this._selected);
}
_selected;
/** The minimum selectable date. */
get minDate() {
return this._minDate;
}
set minDate(value) {
this._minDate = this._getValidDateOrNull(this._adapter.deserialize(value));
}
_minDate;
/** The maximum selectable date. */
get maxDate() {
return this._maxDate;
}
set maxDate(value) {
this._maxDate = this._getValidDateOrNull(this._adapter.deserialize(value));
}
_maxDate;
ngAfterContentInit() {
this._init();
}
/** Handles when a new year is selected. */
_yearSelected(year) {
const month = this._adapter.getMonth(this.activeDate);
const normalizedDate = this._adapter.createDatetime(year, month, 1, 0, 0);
this.selectedChange.emit(this._adapter.createDatetime(year, month, Math.min(this._adapter.getDate(this.activeDate), this._adapter.getNumDaysInMonth(normalizedDate)), this._adapter.getHour(this.activeDate), this._adapter.getMinute(this.activeDate)));
if (this.type === 'year') {
this._userSelection.emit();
}
}
_getActiveCell() {
return getActiveOffset(this._adapter, this.activeDate, this.minDate, this.maxDate);
}
_calendarStateDone() {
this._calendarState = '';
}
/** Initializes this year view. */
_init() {
this._todayYear = this._adapter.getYear(this._adapter.today());
this._yearLabel = this._adapter.getYearName(this.activeDate);
const activeYear = this._adapter.getYear(this.activeDate);
const minYearOfPage = activeYear - getActiveOffset(this._adapter, this.activeDate, this.minDate, this.maxDate);
this._years = [];
for (let i = 0, row = []; i < yearsPerPage; i++) {
row.push(minYearOfPage + i);
if (row.length === yearsPerRow) {
this._years.push(row.map((year) => this._createCellForYear(year)));
row = [];
}
}
}
/** Creates an AswCalendarCell for the given year. */
_createCellForYear(year) {
const yearName = this._adapter.getYearName(this._adapter.createDate(year, 0, 1));
return new AswCalendarCell(year, yearName, yearName, this._shouldEnableYear(year));
}
/** Whether the given year is enabled. */
_shouldEnableYear(year) {
// disable if the year is greater than maxDate lower than minDate
if (year === undefined || year === null || (this.maxDate && year > this._adapter.getYear(this.maxDate)) || (this.minDate && year < this._adapter.getYear(this.minDate))) {
return false;
}
// enable if it reaches here and there's no filter defined
if (!this.dateFilter) {
return true;
}
const firstOfYear = this._adapter.createDate(year, 0, 1);
// If any date in the year is enabled count the year as enabled.
for (let date = firstOfYear; this._adapter.getYear(date) === year; date = this._adapter.addCalendarDays(date, 1)) {
if (this.dateFilter(date)) {
return true;
}
}
return false;
}
/**
* Gets the year in this years range that the given Date falls on.
* Returns null if the given Date is not in this range.
*/
_getYearInCurrentRange(date) {
const year = this._adapter.getYear(date);
return this._isInRange(year) ? year : null;
}
/**
* Validate if the current year is in the current range
* Returns true if is in range else returns false
*/
_isInRange(year) {
return true;
}
/**
* @param obj The object to check.
* @returns The given object if it is both a date instance and valid, otherwise null.
*/
_getValidDateOrNull(obj) {
return this._adapter.isDateInstance(obj) && this._adapter.isValid(obj) ? obj : null;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswMultiYearView, deps: [{ token: i1.DatetimeAdapter, optional: true }, { token: ASW_DATETIME_FORMATS, optional: true }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: AswMultiYearView, selector: "asw-multi-year-view", inputs: { type: "type", dateFilter: "dateFilter", activeDate: "activeDate", selected: "selected", minDate: "minDate", maxDate: "maxDate" }, outputs: { selectedChange: "selectedChange", _userSelection: "_userSelection" }, exportAs: ["aswMultiYearView"], ngImport: i0, template: "<table class=\"asw-calendar-table\" role=\"grid\">\r\n <thead class=\"asw-calendar-table-header\"></thead>\r\n <tbody asw-calendar-body\r\n (@slideCalendar.done)=\"_calendarStateDone()\"\r\n [@slideCalendar]=\"_calendarState\"\r\n [todayValue]=\"_todayYear\"\r\n [rows]=\"_years\"\r\n [numCols]=\"4\"\r\n [activeCell]=\"_getActiveCell()\"\r\n [allowDisabledSelection]=\"true\"\r\n [selectedValue]=\"_selectedYear!\"\r\n (selectedValueChange)=\"_yearSelected($event)\">\r\n </tbody>\r\n</table>\r\n", dependencies: [{ kind: "component", type: i2.AswCalendarBody, selector: "[asw-calendar-body]", inputs: ["label", "rows", "todayValue", "selectedValue", "labelMinRequiredCells", "numCols", "allowDisabledSelection", "activeCell"], outputs: ["selectedValueChange"], exportAs: ["aswCalendarBody"] }], animations: [aswDatetimepickerAnimations.slideCalendar], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswMultiYearView, decorators: [{
type: Component,
args: [{ selector: 'asw-multi-year-view', exportAs: 'aswMultiYearView', animations: [aswDatetimepickerAnimations.slideCalendar], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<table class=\"asw-calendar-table\" role=\"grid\">\r\n <thead class=\"asw-calendar-table-header\"></thead>\r\n <tbody asw-calendar-body\r\n (@slideCalendar.done)=\"_calendarStateDone()\"\r\n [@slideCalendar]=\"_calendarState\"\r\n [todayValue]=\"_todayYear\"\r\n [rows]=\"_years\"\r\n [numCols]=\"4\"\r\n [activeCell]=\"_getActiveCell()\"\r\n [allowDisabledSelection]=\"true\"\r\n [selectedValue]=\"_selectedYear!\"\r\n (selectedValueChange)=\"_yearSelected($event)\">\r\n </tbody>\r\n</table>\r\n" }]
}], ctorParameters: () => [{ type: i1.DatetimeAdapter, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [ASW_DATETIME_FORMATS]
}] }], propDecorators: { type: [{
type: Input
}], dateFilter: [{
type: Input
}], selectedChange: [{
type: Output
}], _userSelection: [{
type: Output
}], activeDate: [{
type: Input
}], selected: [{
type: Input
}], minDate: [{
type: Input
}], maxDate: [{
type: Input
}] } });
export function isSameMultiYearView(dateAdapter, date1, date2, minDate, maxDate) {
const year1 = dateAdapter.getYear(date1);
const year2 = dateAdapter.getYear(date2);
const startingYear = getStartingYear(dateAdapter, minDate, maxDate);
return Math.floor((year1 - startingYear) / yearsPerPage) === Math.floor((year2 - startingYear) / yearsPerPage);
}
/**
* When the multi-year view is first opened, the active year will be in view.
* So we compute how many years are between the active year and the *slot* where our
* "startingYear" will render when paged into view.
*/
export function getActiveOffset(dateAdapter, activeDate, minDate, maxDate) {
const activeYear = dateAdapter.getYear(activeDate);
return euclideanModulo(activeYear - getStartingYear(dateAdapter, minDate, maxDate), yearsPerPage);
}
/**
* We pick a "starting" year such that either the maximum year would be at the end
* or the minimum year would be at the beginning of a page.
*/
function getStartingYear(dateAdapter, minDate, maxDate) {
let startingYear = 0;
if (maxDate) {
const maxYear = dateAdapter.getYear(maxDate);
startingYear = maxYear - yearsPerPage + 1;
}
else if (minDate) {
startingYear = dateAdapter.getYear(minDate);
}
return startingYear;
}
/** Gets remainder that is non-negative, even if first number is negative */
function euclideanModulo(a, b) {
return ((a % b) + b) % b;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGkteWVhci12aWV3LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvZGF0ZXRpbWVwaWNrZXIvbXVsdGkteWVhci12aWV3L211bHRpLXllYXItdmlldy50cyIsIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2RhdGV0aW1lcGlja2VyL211bHRpLXllYXItdmlldy9tdWx0aS15ZWFyLXZpZXcuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQW9CLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZKLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNqRSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMzRSxPQUFPLEVBQUUsb0JBQW9CLEVBQXVDLE1BQU0seUNBQXlDLENBQUM7Ozs7QUFHcEgsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUUvQixNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO0FBRTdCOzs7R0FHRztBQVNILE1BQU0sT0FBTyxnQkFBZ0I7SUE4QkY7SUFDK0I7SUE5QjdDLElBQUksR0FBMEIsTUFBTSxDQUFDO0lBRTlDLDREQUE0RDtJQUNuRCxVQUFVLENBQXdCO0lBRTNDLDBDQUEwQztJQUNoQyxjQUFjLEdBQUcsSUFBSSxZQUFZLEVBQUssQ0FBQztJQUVqRCx1Q0FBdUM7SUFDcEIsY0FBYyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7SUFFN0Qsa0VBQWtFO0lBQ2xFLE1BQU0sQ0FBdUI7SUFFN0Isd0RBQXdEO0lBQ3hELFVBQVUsQ0FBVTtJQUVwQix5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R0FBRyxDQUFDLENBQUM7QUFDN0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyQ29udGVudEluaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBJbnB1dCwgT3B0aW9uYWwsIE91dHB1dCwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGNyZWF0ZU1pc3NpbmdEYXRlSW1wbEVycm9yIH0gZnJvbSAnLi4vZGF0ZXRpbWVwaWNrZXItZXJyb3JzJztcbmltcG9ydCB7IEFzd0NhbGVuZGFyQ2VsbCB9IGZyb20gJy4uL2NhbGVuZGFyLWJvZHkvY2FsZW5kYXItYm9keSc7XG5pbXBvcnQgeyBhc3dEYXRldGltZXBpY2tlckFuaW1hdGlvbnMgfSBmcm9tICcuLi9kYXRldGltZXBpY2tlci1hbmltYXRpb25zJztcbmltcG9ydCB7IEFTV19EQVRFVElNRV9GT1JNQVRTLCBBc3dEYXRldGltZUZvcm1hdHMsIERhdGV0aW1lQWRhcHRlciB9IGZyb20gJ0Bhc29mdHdhcmV3b3JsZC9mb3JtLWJ1aWxkZXItcHJvL2NvbW1vbic7XG5pbXBvcnQgeyBBc3dEYXRldGltZXBpY2tlclR5cGUgfSBmcm9tICcuLi9kYXRldGltZXBpY2tlci10eXBlcyc7XG5cbmV4cG9ydCBjb25zdCB5ZWFyc1BlclBhZ2UgPSAyNDtcblxuZXhwb3J0IGNvbnN0IHllYXJzUGVyUm93ID0gNDtcblxuLyoqXG4gKiBBbiBpbnRlcm5hbCBjb21wb25lbnQgdXNlZCB0byBkaXNwbGF5IG11bHRpcGxlIHllYXJzIGluIHRoZSBkYXRldGltZXBpY2tlci5cbiAqIEBkb2NzLXByaXZhdGVcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdhc3ctbXVsdGkteWVhci12aWV3JyxcbiAgICB0ZW1wbGF0ZVVybDogJ211bHRpLXllYXItdmlldy5odG1sJyxcbiAgICBleHBvcnRBczogJ2Fzd011bHRpWWVhclZpZXcnLFxuICAgIGFuaW1hdGlvbnM6IFthc3dEYXRldGltZXBpY2tlckFuaW1hdGlvbnMuc2xpZGVDYWxlbmRhcl0sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBBc3dNdWx0aVllYXJWaWV3PEQ+IGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCB7XG4gICAgQElucHV0KCkgdHlwZTogQXN3RGF0ZXRpbWVwaWNrZXJUeXBlID0gJ2RhdGUnO1xuXG4gICAgLyoqIEEgZnVuY3Rpb24gdXNlZCB0byBmaWx0ZXIgd2hpY2ggZGF0ZXMgYXJlIHNlbGVjdGFibGUuICovXG4gICAgQElucHV0KCkgZGF0ZUZpbHRlciE6IChkYXRlOiBEKSA9PiBib29sZWFuO1xuXG4gICAgLyoqIEVtaXRzIHdoZW4gYSBuZXcgbW9udGggaXMgc2VsZWN0ZWQuICovXG4gICAgQE91dHB1dCgpIHNlbGVjdGVkQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEPigpO1xuXG4gICAgLyoqIEVtaXRzIHdoZW4gYW55IGRhdGUgaXMgc2VsZWN0ZWQuICovXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IF91c2VyU2VsZWN0aW9uID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gICAgLyoqIEdyaWQgb2YgY2FsZW5kYXIgY2VsbHMgcmVwcmVzZW50aW5nIHRoZSB5ZWFycyBpbiB0aGUgcmFuZ2UuICovXG4gICAgX3llYXJzITogQXN3Q2FsZW5kYXJDZWxsW11bXTtcblxuICAgIC8qKiBUaGUgbGFiZWwgZm9yIHRoaXMgeWVhciByYW5nZSAoZS5nLiBcIjIwMDAtMjAyMFwiKS4gKi9cbiAgICBfeWVhckxhYmVsITogc3RyaW5nO1xuXG4gICAgLyoqIFRoZSB5ZWFyIGluIHRoaXMgcmFuZ2UgdGhhdCB0b2RheSBmYWxscyBvbi4gTnVsbCBpZiB0b2RheSBpcyBpbiBhIGRpZmZlcmVudCByYW5nZS4gKi9cbiAgICBfdG9kYXlZZWFyITogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHllYXIgaW4gdGhpcyByYW5nZSB0aGF0IHRoZSBzZWxlY3RlZCBEYXRlIGZhbGxzIG9uLlxuICAgICAqIE51bGwgaWYgdGhlIHNlbGVjdGVkIERhdGUgaXMgaW4gYSBkaWZmZXJlbnQgcmFuZ2UuXG4gICAgICovXG4gICAgX3NlbGVjdGVkWWVhciE6IG51bWJlciB8IG51bGw7XG5cbiAgICBfY2FsZW5kYXJTdGF0ZSE6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBAT3B0aW9uYWwoKSBwdWJsaWMgX2FkYXB0ZXI6IERhdGV0aW1lQWRhcHRlcjxEPixcbiAgICAgICAgQE9wdGlvbmFsKCkgQEluamVjdChBU1dfREFURVRJTUVfRk9STUFUUykgcHJpdmF0ZSBfZGF0ZUZvcm1hdHM6IEFzd0RhdGV0aW1lRm9ybWF0c1xuICAgICkge1xuICAgICAgICBpZiAoIXRoaXMuX2FkYXB0ZXIpIHtcbiAgICAgICAgICAgIHRocm93IGNyZWF0ZU1pc3NpbmdEYXRlSW1wbEVycm9yKCdEYXRldGltZUFkYXB0ZXInKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5fZGF0ZUZvcm1hdHMpIHtcbiAgICAgICAgICAgIHRocm93IGNyZWF0ZU1pc3NpbmdEYXRlSW1wbEVycm9yKCdBU1dfREFURVRJTUVfRk9STUFUUycpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fYWN0aXZlRGF0ZSA9IHRoaXMuX2FkYXB0ZXIudG9kYXkoKTtcbiAgICB9XG5cbiAgICAvKiogVGhlIGRhdGUgdG8gZGlzcGxheSBpbiB0aGlzIG11bHRpIHllYXIgdmlldyAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGFjdGl2ZURhdGUoKTogRCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hY3RpdmVEYXRlO1xuICAgIH1cbiAgICBzZXQgYWN0aXZlRGF0ZSh2YWx1ZTogRCkge1xuICAgICAgICBjb25zdCBvbGRBY3RpdmVEYXRlID0gdGhpcy5fYWN0aXZlRGF0ZTtcbiAgICAgICAgdGhpcy5fYWN0aXZlRGF0ZSA9IHZhbHVlIHx8IHRoaXMuX2FkYXB0ZXIudG9kYXkoKTtcbiAgICAgICAgaWYgKG9sZEFjdGl2ZURhdGUgJiYgdGhpcy5fYWN0aXZlRGF0ZSAmJiAhaXNTYW1lTXVsdGlZZWFyVmlldyh0aGlzLl9hZGFwdGVyLCBvbGRBY3RpdmVEYXRlLCB0aGlzLl9hY3RpdmVEYXRlLCB0aGlzLm1pbkRhdGUsIHRoaXMubWF4RGF0ZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX2luaXQoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBwcml2YXRlIF9hY3RpdmVEYXRlOiBEO1xuXG4gICAgLyoqIFRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgZGF0ZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBzZWxlY3RlZCgpOiBEIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkO1xuICAgIH1cbiAgICBzZXQgc2VsZWN0ZWQodmFsdWU6IEQpIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWQgPSB2YWx1ZTtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWRZZWFyID0gdGhpcy5fc2VsZWN0ZWQgJiYgdGhpcy5fYWRhcHRlci5nZXRZZWFyKHRoaXMuX3NlbGVjdGVkKTtcbiAgICB9XG4gICAgcHJpdmF0ZSBfc2VsZWN0ZWQhOiBEO1xuXG4gICAgLyoqIFRoZSBtaW5pbXVtIHNlbGVjdGFibGUgZGF0ZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBtaW5EYXRlKCk6IEQgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21pbkRhdGU7XG4gICAgfVxuICAgIHNldCBtaW5EYXRlKHZhbHVlOiBEIHwgbnVsbCkge1xuICAgICAgICB0aGlzLl9taW5EYXRlID0gdGhpcy5fZ2V0VmFsaWREYXRlT3JOdWxsKHRoaXMuX2FkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgICB9XG4gICAgcHJpdmF0ZSBfbWluRGF0ZSE6IEQgfCBudWxsO1xuXG4gICAgLyoqIFRoZSBtYXhpbXVtIHNlbGVjdGFibGUgZGF0ZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBtYXhEYXRlKCk6IEQgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21heERhdGU7XG4gICAgfVxuICAgIHNldCBtYXhEYXRlKHZhbHVlOiBEIHwgbnVsbCkge1xuICAgICAgICB0aGlzLl9tYXhEYXRlID0gdGhpcy5fZ2V0VmFsaWREYXRlT3JOdWxsKHRoaXMuX2FkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgICB9XG4gICAgcHJpdmF0ZSBfbWF4RGF0ZSE6IEQgfCBudWxsO1xuXG4gICAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgICAgICB0aGlzLl9pbml0KCk7XG4gICAgfVxuXG4gICAgLyoqIEhhbmRsZXMgd2hlbiBhIG5ldyB5ZWFyIGlzIHNlbGVjdGVkLiAqL1xuICAgIF95ZWFyU2VsZWN0ZWQoeWVhcjogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IG1vbnRoID0gdGhpcy5fYWRhcHRlci5nZXRNb250aCh0aGlzLmFjdGl2ZURhdGUpO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkRGF0ZSA9IHRoaXMuX2FkYXB0ZXIuY3JlYXRlRGF0ZXRpbWUoeWVhciwgbW9udGgsIDEsIDAsIDApO1xuXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRDaGFuZ2UuZW1pdChcbiAgICAgICAgICAgIHRoaXMuX2FkYXB0ZXIuY3JlYXRlRGF0ZXRpbWUoeWVhciwgbW9udGgsIE1hdGgubWluKHRoaXMuX2FkYXB0ZXIuZ2V0RGF0ZSh0aGlzLmFjdGl2ZURhdGUpLCB0aGlzLl9hZGFwdGVyLmdldE51bURheXNJbk1vbnRoKG5vcm1hbGl6ZWREYXRlKSksIHRoaXMuX2FkYXB0ZXIuZ2V0SG91cih0aGlzLmFjdGl2ZURhdGUpLCB0aGlzLl9hZGFwdGVyLmdldE1pbnV0ZSh0aGlzLmFjdGl2ZURhdGUpKVxuICAgICAgICApO1xuXG4gICAgICAgIGlmICh0aGlzLnR5cGUgPT09ICd5ZWFyJykge1xuICAgICAgICAgICAgdGhpcy5fdXNlclNlbGVjdGlvbi5lbWl0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfZ2V0QWN0aXZlQ2VsbCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gZ2V0QWN0aXZlT2Zmc2V0KHRoaXMuX2FkYXB0ZXIsIHRoaXMuYWN0aXZlRGF0ZSwgdGhpcy5taW5EYXRlLCB0aGlzLm1heERhdGUpO1xuICAgIH1cblxuICAgIF9jYWxlbmRhclN0YXRlRG9uZSgpIHtcbiAgICAgICAgdGhpcy5fY2FsZW5kYXJTdGF0ZSA9ICcnO1xuICAgIH1cblxuICAgIC8qKiBJbml0aWFsaXplcyB0aGlzIHllYXIgdmlldy4gKi9cbiAgICBwcml2YXRlIF9pbml0KCkge1xuICAgICAgICB0aGlzLl90b2RheVllYXIgPSB0aGlzLl9hZGFwdGVyLmdldFllYXIodGhpcy5fYWRhcHRlci50b2RheSgpKTtcbiAgICAgICAgdGhpcy5feWVhckxhYmVsID0gdGhpcy5fYWRhcHRlci5nZXRZZWFyTmFtZSh0aGlzLmFjdGl2ZURhdGUpO1xuXG4gICAgICAgIGNvbnN0IGFjdGl2ZVllYXIgPSB0aGlzLl9hZGFwdGVyLmdldFllYXIodGhpcy5hY3RpdmVEYXRlKTtcblxuICAgICAgICBjb25zdCBtaW5ZZWFyT2ZQYWdlID0gYWN0aXZlWWVhciAtIGdldEFjdGl2ZU9mZnNldCh0aGlzLl9hZGFwdGVyLCB0aGlzLmFjdGl2ZURhdGUsIHRoaXMubWluRGF0ZSwgdGhpcy5tYXhEYXRlKTtcblxuICAgICAgICB0aGlzLl95ZWFycyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMCwgcm93OiBudW1iZXJbXSA9IFtdOyBpIDwgeWVhcnNQZXJQYWdlOyBpKyspIHtcbiAgICAgICAgICAgIHJvdy5wdXNoKG1pblllYXJPZlBhZ2UgKyBpKTtcbiAgICAgICAgICAgIGlmIChyb3cubGVuZ3RoID09PSB5ZWFyc1BlclJvdykge1xuICAgICAgICAgICAgICAgIHRoaXMuX3llYXJzLnB1c2gocm93Lm1hcCgoeWVhcikgPT4gdGhpcy5fY3JlYXRlQ2VsbEZvclllYXIoeWVhcikpKTtcbiAgICAgICAgICAgICAgICByb3cgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBDcmVhdGVzIGFuIEFzd0NhbGVuZGFyQ2VsbCBmb3IgdGhlIGdpdmVuIHllYXIuICovXG4gICAgcHJpdmF0ZSBfY3JlYXRlQ2VsbEZvclllYXIoeWVhcjogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IHllYXJOYW1lID0gdGhpcy5fYWRhcHRlci5nZXRZZWFyTmFtZSh0aGlzLl9hZGFwdGVyLmNyZWF0ZURhdGUoeWVhciwgMCwgMSkpO1xuICAgICAgICByZXR1cm4gbmV3IEFzd0NhbGVuZGFyQ2VsbCh5ZWFyLCB5ZWFyTmFtZSwgeWVhck5hbWUsIHRoaXMuX3Nob3VsZEVuYWJsZVllYXIoeWVhcikpO1xuICAgIH1cblxuICAgIC8qKiBXaGV0aGVyIHRoZSBnaXZlbiB5ZWFyIGlzIGVuYWJsZWQuICovXG4gICAgcHJpdmF0ZSBfc2hvdWxkRW5hYmxlWWVhcih5ZWFyOiBudW1iZXIpIHtcbiAgICAgICAgLy8gZGlzYWJsZSBpZiB0aGUgeWVhciBpcyBncmVhdGVyIHRoYW4gbWF4RGF0ZSBsb3dlciB0aGFuIG1pbkRhdGVcbiAgICAgICAgaWYgKHllYXIgPT09IHVuZGVmaW5lZCB8fCB5ZWFyID09PSBudWxsIHx8ICh0aGlzLm1heERhdGUgJiYgeWVhciA+IHRoaXMuX2FkYXB0ZXIuZ2V0WWVhcih0aGlzLm1heERhdGUpKSB8fCAodGhpcy5taW5EYXRlICYmIHllYXIgPCB0aGlzLl9hZGFwdGVyLmdldFllYXIodGhpcy5taW5EYXRlKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGVuYWJsZSBpZiBpdCByZWFjaGVzIGhlcmUgYW5kIHRoZXJlJ3Mgbm8gZmlsdGVyIGRlZmluZWRcbiAgICAgICAgaWYgKCF0aGlzLmRhdGVGaWx0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmlyc3RPZlllYXIgPSB0aGlzLl9hZGFwdGVyLmNyZWF0ZURhdGUoeWVhciwgMCwgMSk7XG5cbiAgICAgICAgLy8gSWYgYW55IGRhdGUgaW4gdGhlIHllYXIgaXMgZW5hYmxlZCBjb3VudCB0aGUgeWVhciBhcyBlbmFibGVkLlxuICAgICAgICBmb3IgKGxldCBkYXRlID0gZmlyc3RPZlllYXI7IHRoaXMuX2FkYXB0ZXIuZ2V0WWVhcihkYXRlKSA9PT0geWVhcjsgZGF0ZSA9IHRoaXMuX2FkYXB0ZXIuYWRkQ2FsZW5kYXJEYXlzKGRhdGUsIDEpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5kYXRlRmlsdGVyKGRhdGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgeWVhciBpbiB0aGlzIHllYXJzIHJhbmdlIHRoYXQgdGhlIGdpdmVuIERhdGUgZmFsbHMgb24uXG4gICAgICogUmV0dXJucyBudWxsIGlmIHRoZSBnaXZlbiBEYXRlIGlzIG5vdCBpbiB0aGlzIHJhbmdlLlxuICAgICAqL1xuICAgIHByaXZhdGUgX2dldFllYXJJbkN1cnJlbnRSYW5nZShkYXRlOiBEKSB7XG4gICAgICAgIGNvbnN0IHllYXIgPSB0aGlzLl9hZGFwdGVyLmdldFllYXIoZGF0ZSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0luUmFuZ2UoeWVhcikgPyB5ZWFyIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSBpZiB0aGUgY3VycmVudCB5ZWFyIGlzIGluIHRoZSBjdXJyZW50IHJhbmdlXG4gICAgICogUmV0dXJucyB0cnVlIGlmIGlzIGluIHJhbmdlIGVsc2UgcmV0dXJucyBmYWxzZVxuICAgICAqL1xuICAgIHByaXZhdGUgX2lzSW5SYW5nZSh5ZWFyOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9iaiBUaGUgb2JqZWN0IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIFRoZSBnaXZlbiBvYmplY3QgaWYgaXQgaXMgYm90aCBhIGRhdGUgaW5zdGFuY2UgYW5kIHZhbGlkLCBvdGhlcndpc2UgbnVsbC5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9nZXRWYWxpZERhdGVPck51bGwob2JqOiBhbnkpOiBEIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGFwdGVyLmlzRGF0ZUluc3RhbmNlKG9iaikgJiYgdGhpcy5fYWRhcHRlci5pc1ZhbGlkKG9iaikgPyBvYmogOiBudWxsO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU2FtZU11bHRpWWVhclZpZXc8RD4oZGF0ZUFkYXB0ZXI6IERhdGV0aW1lQWRhcHRlcjxEPiwgZGF0ZTE6IEQsIGRhdGUyOiBELCBtaW5EYXRlOiBEIHwgbnVsbCwgbWF4RGF0ZTogRCB8IG51bGwpOiBib29sZWFuIHtcbiAgICBjb25zdCB5ZWFyMSA9IGRhdGVBZGFwdGVyLmdldFllYXIoZGF0ZTEpO1xuICAgIGNvbnN0IHllYXIyID0gZGF0ZUFkYXB0ZXIuZ2V0WWVhcihkYXRlMik7XG4gICAgY29uc3Qgc3RhcnRpbmdZZWFyID0gZ2V0U3RhcnRpbmdZZWFyKGRhdGVBZGFwdGVyLCBtaW5EYXRlLCBtYXhEYXRlKTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcigoeWVhcjEgLSBzdGFydGluZ1llYXIpIC8geWVhcnNQZXJQYWdlKSA9PT0gTWF0aC5mbG9vcigoeWVhcjIgLSBzdGFydGluZ1llYXIpIC8geWVhcnNQZXJQYWdlKTtcbn1cblxuLyoqXG4gKiBXaGVuIHRoZSBtdWx0aS15ZWFyIHZpZXcgaXMgZmlyc3Qgb3BlbmVkLCB0aGUgYWN0aXZlIHllYXIgd2lsbCBiZSBpbiB2aWV3LlxuICogU28gd2UgY29tcHV0ZSBob3cgbWFueSB5ZWFycyBhcmUgYmV0d2VlbiB0aGUgYWN0aXZlIHllYXIgYW5kIHRoZSAqc2xvdCogd2hlcmUgb3VyXG4gKiBcInN0YXJ0aW5nWWVhclwiIHdpbGwgcmVuZGVyIHdoZW4gcGFnZWQgaW50byB2aWV3LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZlT2Zmc2V0PEQ+KGRhdGVBZGFwdGVyOiBEYXRldGltZUFkYXB0ZXI8RD4sIGFjdGl2ZURhdGU6IEQsIG1pbkRhdGU6IEQgfCBudWxsLCBtYXhEYXRlOiBEIHwgbnVsbCk6IG51bWJlciB7XG4gICAgY29uc3QgYWN0aXZlWWVhciA9IGRhdGVBZGFwdGVyLmdldFllYXIoYWN0aXZlRGF0ZSk7XG4gICAgcmV0dXJuIGV1Y2xpZGVhbk1vZHVsbyhhY3RpdmVZZWFyIC0gZ2V0U3RhcnRpbmdZZWFyKGRhdGVBZGFwdGVyLCBtaW5EYXRlLCBtYXhEYXRlKSwgeWVhcnNQZXJQYWdlKTtcbn1cblxuLyoqXG4gKiBXZSBwaWNrIGEgXCJzdGFydGluZ1wiIHllYXIgc3VjaCB0aGF0IGVpdGhlciB0aGUgbWF4aW11bSB5ZWFyIHdvdWxkIGJlIGF0IHRoZSBlbmRcbiAqIG9yIHRoZSBtaW5pbXVtIHllYXIgd291bGQgYmUgYXQgdGhlIGJlZ2lubmluZyBvZiBhIHBhZ2UuXG4gKi9cbmZ1bmN0aW9uIGdldFN0YXJ0aW5nWWVhcjxEPihkYXRlQWRhcHRlcjogRGF0ZXRpbWVBZGFwdGVyPEQ+LCBtaW5EYXRlOiBEIHwgbnVsbCwgbWF4RGF0ZTogRCB8IG51bGwpOiBudW1iZXIge1xuICAgIGxldCBzdGFydGluZ1llYXIgPSAwO1xuICAgIGlmIChtYXhEYXRlKSB7XG4gICAgICAgIGNvbnN0IG1heFllYXIgPSBkYXRlQWRhcHRlci5nZXRZZWFyKG1heERhdGUpO1xuICAgICAgICBzdGFydGluZ1llYXIgPSBtYXhZZWFyIC0geWVhcnNQZXJQYWdlICsgMTtcbiAgICB9IGVsc2UgaWYgKG1pbkRhdGUpIHtcbiAgICAgICAgc3RhcnRpbmdZZWFyID0gZGF0ZUFkYXB0ZXIuZ2V0WWVhcihtaW5EYXRlKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0YXJ0aW5nWWVhcjtcbn1cblxuLyoqIEdldHMgcmVtYWluZGVyIHRoYXQgaXMgbm9uLW5lZ2F0aXZlLCBldmVuIGlmIGZpcnN0IG51bWJlciBpcyBuZWdhdGl2ZSAqL1xuZnVuY3Rpb24gZXVjbGlkZWFuTW9kdWxvKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gKChhICUgYikgKyBiKSAlIGI7XG59XG4iLCI8dGFibGUgY2xhc3M9XCJhc3ctY2FsZW5kYXItdGFibGVcIiByb2xlPVwiZ3JpZFwiPlxyXG4gICAgPHRoZWFkIGNsYXNzPVwiYXN3LWNhbGVuZGFyLXRhYmxlLWhlYWRlclwiPjwvdGhlYWQ+XHJcbiAgICA8dGJvZHkgYXN3LWNhbGVuZGFyLWJvZHlcclxuICAgICAgICAoQHNsaWRlQ2FsZW5kYXIuZG9uZSk9XCJfY2FsZW5kYXJTdGF0ZURvbmUoKVwiXHJcbiAgICAgICAgW0BzbGlkZUNhbGVuZGFyXT1cIl9jYWxlbmRhclN0YXRlXCJcclxuICAgICAgICBbdG9kYXlWYWx1ZV09XCJfdG9kYXlZZWFyXCJcclxuICAgICAgICBbcm93c109XCJfeWVhcnNcIlxyXG4gICAgICAgIFtudW1Db2xzXT1cIjRcIlxyXG4gICAgICAgIFthY3RpdmVDZWxsXT1cIl9nZXRBY3RpdmVDZWxsKClcIlxyXG4gICAgICAgIFthbGxvd0Rpc2FibGVkU2VsZWN0aW9uXT1cInRydWVcIlxyXG4gICAgICAgIFtzZWxlY3RlZFZhbHVlXT1cIl9zZWxlY3RlZFllYXIhXCJcclxuICAgICAgICAoc2VsZWN0ZWRWYWx1ZUNoYW5nZSk9XCJfeWVhclNlbGVjdGVkKCRldmVudClcIj5cclxuICAgIDwvdGJvZHk+XHJcbjwvdGFibGU+XHJcbiJdfQ==