UNPKG

@herculesproject/datetime-picker

Version:
619 lines 61.9 kB
/** * @fileoverview added by tsickle * Generated from: lib/month-view.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { DOWN_ARROW, END, ENTER, HOME, LEFT_ARROW, PAGE_DOWN, PAGE_UP, RIGHT_ARROW, UP_ARROW, SPACE, ESCAPE, } from '@angular/cdk/keycodes'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Inject, Input, Optional, Output, ViewEncapsulation, ViewChild, } from '@angular/core'; import { Directionality } from '@angular/cdk/bidi'; import { Subscription } from 'rxjs'; import { startWith } from 'rxjs/operators'; import { DateRange } from '@angular/material/datepicker'; import { NgxMatCalendarBody, NgxMatCalendarCell } from './calendar-body'; import { NGX_MAT_DATE_FORMATS } from './core/date-formats'; import { NgxMatDateAdapter } from './core/date-adapter'; import { NGX_MAT_DATE_RANGE_SELECTION_STRATEGY } from './date-range-selection-strategy'; import { createMissingDateImplError } from './utils/date-utils'; /** @type {?} */ const DAYS_PER_WEEK = 7; /** * An internal component used to display a single month in the datepicker. * \@docs-private * @template D */ export class NgxMatMonthView { /** * @param {?} _changeDetectorRef * @param {?} _dateFormats * @param {?} _dateAdapter * @param {?=} _dir * @param {?=} _rangeStrategy */ constructor(_changeDetectorRef, _dateFormats, _dateAdapter, _dir, _rangeStrategy) { this._changeDetectorRef = _changeDetectorRef; this._dateFormats = _dateFormats; this._dateAdapter = _dateAdapter; this._dir = _dir; this._rangeStrategy = _rangeStrategy; this._rerenderSubscription = Subscription.EMPTY; /** * Emits when a new date is selected. */ this.selectedChange = new EventEmitter(); /** * Emits when any date is selected. */ this._userSelection = new EventEmitter(); /** * Emits when any date is activated. */ this.activeDateChange = new EventEmitter(); if (!this._dateAdapter) { throw createMissingDateImplError('NgxMatDateAdapter'); } if (!this._dateFormats) { throw createMissingDateImplError('NGX_MAT_DATE_FORMATS'); } this._activeDate = this._dateAdapter.today(); } /** * The date to display in this month view (everything other than the month and year is ignored). * @return {?} */ get activeDate() { return this._activeDate; } /** * @param {?} value * @return {?} */ set activeDate(value) { /** @type {?} */ const oldActiveDate = this._activeDate; /** @type {?} */ const validDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)) || this._dateAdapter.today(); this._activeDate = this._dateAdapter.clampDate(validDate, this.minDate, this.maxDate); if (!this._hasSameMonthAndYear(oldActiveDate, this._activeDate)) { this._init(); } } /** * The currently selected date. * @return {?} */ get selected() { return this._selected; } /** * @param {?} value * @return {?} */ set selected(value) { if (value instanceof DateRange) { this._selected = value; } else { this._selected = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); } this._setRanges(this._selected); } /** * The minimum selectable date. * @return {?} */ get minDate() { return this._minDate; } /** * @param {?} value * @return {?} */ set minDate(value) { this._minDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); } /** * The maximum selectable date. * @return {?} */ get maxDate() { return this._maxDate; } /** * @param {?} value * @return {?} */ set maxDate(value) { this._maxDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); } /** * @return {?} */ ngAfterContentInit() { this._rerenderSubscription = this._dateAdapter.localeChanges .pipe(startWith(null)) .subscribe((/** * @return {?} */ () => this._init())); } /** * @return {?} */ ngOnDestroy() { this._rerenderSubscription.unsubscribe(); } /** * Handles when a new date is selected. * @param {?} event * @return {?} */ _dateSelected(event) { /** @type {?} */ const date = event.value; /** @type {?} */ const selectedYear = this._dateAdapter.getYear(this.activeDate); /** @type {?} */ const selectedMonth = this._dateAdapter.getMonth(this.activeDate); /** @type {?} */ const selectedDate = this._dateAdapter.createDate(selectedYear, selectedMonth, date); /** @type {?} */ let rangeStartDate; /** @type {?} */ let rangeEndDate; if (this._selected instanceof DateRange) { rangeStartDate = this._getDateInCurrentMonth(this._selected.start); rangeEndDate = this._getDateInCurrentMonth(this._selected.end); } else { rangeStartDate = rangeEndDate = this._getDateInCurrentMonth(this._selected); } if (rangeStartDate !== date || rangeEndDate !== date) { this.selectedChange.emit(selectedDate); } this._userSelection.emit({ value: selectedDate, event: event.event }); } /** * Handles keydown events on the calendar body when calendar is in month view. * @param {?} event * @return {?} */ _handleCalendarBodyKeydown(event) { // TODO(mmalerba): We currently allow keyboard navigation to disabled dates, but just prevent // disabled ones from being selected. This may not be ideal, we should look into whether // navigation should skip over disabled dates, and if so, how to implement that efficiently. // TODO(mmalerba): We currently allow keyboard navigation to disabled dates, but just prevent // disabled ones from being selected. This may not be ideal, we should look into whether // navigation should skip over disabled dates, and if so, how to implement that efficiently. /** @type {?} */ const oldActiveDate = this._activeDate; /** @type {?} */ const isRtl = this._isRtl(); switch (event.keyCode) { case LEFT_ARROW: this.activeDate = this._dateAdapter.addCalendarDays(this._activeDate, isRtl ? 1 : -1); break; case RIGHT_ARROW: this.activeDate = this._dateAdapter.addCalendarDays(this._activeDate, isRtl ? -1 : 1); break; case UP_ARROW: this.activeDate = this._dateAdapter.addCalendarDays(this._activeDate, -7); break; case DOWN_ARROW: this.activeDate = this._dateAdapter.addCalendarDays(this._activeDate, 7); break; case HOME: this.activeDate = this._dateAdapter.addCalendarDays(this._activeDate, 1 - this._dateAdapter.getDate(this._activeDate)); break; case END: this.activeDate = this._dateAdapter.addCalendarDays(this._activeDate, (this._dateAdapter.getNumDaysInMonth(this._activeDate) - this._dateAdapter.getDate(this._activeDate))); break; case PAGE_UP: this.activeDate = event.altKey ? this._dateAdapter.addCalendarYears(this._activeDate, -1) : this._dateAdapter.addCalendarMonths(this._activeDate, -1); break; case PAGE_DOWN: this.activeDate = event.altKey ? this._dateAdapter.addCalendarYears(this._activeDate, 1) : this._dateAdapter.addCalendarMonths(this._activeDate, 1); break; case ENTER: case SPACE: if (!this.dateFilter || this.dateFilter(this._activeDate)) { this._dateSelected({ value: this._dateAdapter.getDate(this._activeDate), event }); // Prevent unexpected default actions such as form submission. event.preventDefault(); } return; case ESCAPE: // Abort the current range selection if the user presses escape mid-selection. if (this._previewEnd != null) { this._previewStart = this._previewEnd = null; this.selectedChange.emit(null); this._userSelection.emit({ value: null, event }); event.preventDefault(); event.stopPropagation(); // Prevents the overlay from closing. } return; default: // Don't prevent default or focus active cell on keys that we don't explicitly handle. return; } if (this._dateAdapter.compareDate(oldActiveDate, this.activeDate)) { this.activeDateChange.emit(this.activeDate); } this._focusActiveCell(); // Prevent unexpected default actions such as form submission. event.preventDefault(); } /** * Initializes this month view. * @return {?} */ _init() { this._setRanges(this.selected); this._todayDate = this._getCellCompareValue(this._dateAdapter.today()); this._monthLabel = this._dateAdapter.getMonthNames('short')[this._dateAdapter.getMonth(this.activeDate)] .toLocaleUpperCase(); /** @type {?} */ let firstOfMonth = this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), this._dateAdapter.getMonth(this.activeDate), 1); this._firstWeekOffset = (DAYS_PER_WEEK + this._dateAdapter.getDayOfWeek(firstOfMonth) - this._dateAdapter.getFirstDayOfWeek()) % DAYS_PER_WEEK; this._initWeekdays(); this._createWeekCells(); this._changeDetectorRef.markForCheck(); } /** * Focuses the active cell after the microtask queue is empty. * @param {?=} movePreview * @return {?} */ _focusActiveCell(movePreview) { this._matCalendarBody._focusActiveCell(movePreview); } /** * Called when the user has activated a new cell and the preview needs to be updated. * @param {?} __0 * @return {?} */ _previewChanged({ event, value: cell }) { if (this._rangeStrategy) { // We can assume that this will be a range, because preview // events aren't fired for single date selections. /** @type {?} */ const value = cell ? (/** @type {?} */ (cell.rawValue)) : null; /** @type {?} */ const previewRange = this._rangeStrategy.createPreview(value, (/** @type {?} */ (this.selected)), event); this._previewStart = this._getCellCompareValue(previewRange.start); this._previewEnd = this._getCellCompareValue(previewRange.end); // Note that here we need to use `detectChanges`, rather than `markForCheck`, because // the way `_focusActiveCell` is set up at the moment makes it fire at the wrong time // when navigating one month back using the keyboard which will cause this handler // to throw a "changed after checked" error when updating the preview state. this._changeDetectorRef.detectChanges(); } } /** * Initializes the weekdays. * @private * @return {?} */ _initWeekdays() { /** @type {?} */ const firstDayOfWeek = this._dateAdapter.getFirstDayOfWeek(); /** @type {?} */ const narrowWeekdays = this._dateAdapter.getDayOfWeekNames('narrow'); /** @type {?} */ const longWeekdays = this._dateAdapter.getDayOfWeekNames('long'); // Rotate the labels for days of the week based on the configured first day of the week. /** @type {?} */ let weekdays = longWeekdays.map((/** * @param {?} long * @param {?} i * @return {?} */ (long, i) => { return { long, narrow: narrowWeekdays[i] }; })); this._weekdays = weekdays.slice(firstDayOfWeek).concat(weekdays.slice(0, firstDayOfWeek)); } /** * Creates MatCalendarCells for the dates in this month. * @private * @return {?} */ _createWeekCells() { /** @type {?} */ const daysInMonth = this._dateAdapter.getNumDaysInMonth(this.activeDate); /** @type {?} */ const dateNames = this._dateAdapter.getDateNames(); this._weeks = [[]]; for (let i = 0, cell = this._firstWeekOffset; i < daysInMonth; i++, cell++) { if (cell == DAYS_PER_WEEK) { this._weeks.push([]); cell = 0; } /** @type {?} */ const date = this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), this._dateAdapter.getMonth(this.activeDate), i + 1); /** @type {?} */ const enabled = this._shouldEnableDate(date); /** @type {?} */ const ariaLabel = this._dateAdapter.format(date, this._dateFormats.display.dateA11yLabel); /** @type {?} */ const cellClasses = this.dateClass ? this.dateClass(date) : undefined; this._weeks[this._weeks.length - 1].push(new NgxMatCalendarCell(i + 1, dateNames[i], ariaLabel, enabled, cellClasses, (/** @type {?} */ (this._getCellCompareValue(date))), date)); } } /** * Date filter for the month * @private * @param {?} date * @return {?} */ _shouldEnableDate(date) { return !!date && (!this.minDate || this._dateAdapter.compareDate(date, this.minDate) >= 0) && (!this.maxDate || this._dateAdapter.compareDate(date, this.maxDate) <= 0) && (!this.dateFilter || this.dateFilter(date)); } /** * Gets the date in this month that the given Date falls on. * Returns null if the given Date is in another month. * @private * @param {?} date * @return {?} */ _getDateInCurrentMonth(date) { return date && this._hasSameMonthAndYear(date, this.activeDate) ? this._dateAdapter.getDate(date) : null; } /** * Checks whether the 2 dates are non-null and fall within the same month of the same year. * @private * @param {?} d1 * @param {?} d2 * @return {?} */ _hasSameMonthAndYear(d1, d2) { return !!(d1 && d2 && this._dateAdapter.getMonth(d1) == this._dateAdapter.getMonth(d2) && this._dateAdapter.getYear(d1) == this._dateAdapter.getYear(d2)); } /** * Gets the value that will be used to one cell to another. * @private * @param {?} date * @return {?} */ _getCellCompareValue(date) { if (date) { // We use the time since the Unix epoch to compare dates in this view, rather than the // cell values, because we need to support ranges that span across multiple months/years. /** @type {?} */ const year = this._dateAdapter.getYear(date); /** @type {?} */ const month = this._dateAdapter.getMonth(date); /** @type {?} */ const day = this._dateAdapter.getDate(date); return new Date(year, month, day).getTime(); } return null; } /** * @private * @param {?} obj The object to check. * @return {?} The given object if it is both a date instance and valid, otherwise null. */ _getValidDateOrNull(obj) { return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null; } /** * Determines whether the user has the RTL layout direction. * @private * @return {?} */ _isRtl() { return this._dir && this._dir.value === 'rtl'; } /** * Sets the current range based on a model value. * @private * @param {?} selectedValue * @return {?} */ _setRanges(selectedValue) { if (selectedValue instanceof DateRange) { this._rangeStart = this._getCellCompareValue(selectedValue.start); this._rangeEnd = this._getCellCompareValue(selectedValue.end); this._isRange = true; } else { this._rangeStart = this._rangeEnd = this._getCellCompareValue(selectedValue); this._isRange = false; } this._comparisonRangeStart = this._getCellCompareValue(this.comparisonStart); this._comparisonRangeEnd = this._getCellCompareValue(this.comparisonEnd); } } NgxMatMonthView.decorators = [ { type: Component, args: [{ selector: 'ngx-mat-month-view', template: "<table class=\"mat-calendar-table\" role=\"presentation\">\n <thead class=\"mat-calendar-table-header\">\n <tr>\n <th scope=\"col\" *ngFor=\"let day of _weekdays\" [attr.aria-label]=\"day.long\">{{day.narrow}}</th>\n </tr>\n <tr><th class=\"mat-calendar-table-header-divider\" colspan=\"7\" aria-hidden=\"true\"></th></tr>\n </thead>\n <tbody ngx-mat-calendar-body\n [label]=\"_monthLabel\"\n [rows]=\"_weeks\"\n [todayValue]=\"_todayDate!\"\n [startValue]=\"_rangeStart!\"\n [endValue]=\"_rangeEnd!\"\n [comparisonStart]=\"_comparisonRangeStart\"\n [comparisonEnd]=\"_comparisonRangeEnd\"\n [previewStart]=\"_previewStart\"\n [previewEnd]=\"_previewEnd\"\n [isRange]=\"_isRange\"\n [labelMinRequiredCells]=\"3\"\n [activeCell]=\"_dateAdapter.getDate(activeDate) - 1\"\n (selectedValueChange)=\"_dateSelected($event)\"\n (previewChange)=\"_previewChanged($event)\"\n (keydown)=\"_handleCalendarBodyKeydown($event)\">\n </tbody>\n</table>\n", exportAs: 'ngxMatMonthView', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush }] } ]; /** @nocollapse */ NgxMatMonthView.ctorParameters = () => [ { type: ChangeDetectorRef }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NGX_MAT_DATE_FORMATS,] }] }, { type: NgxMatDateAdapter, decorators: [{ type: Optional }] }, { type: Directionality, decorators: [{ type: Optional }] }, { type: undefined, decorators: [{ type: Inject, args: [NGX_MAT_DATE_RANGE_SELECTION_STRATEGY,] }, { type: Optional }] } ]; NgxMatMonthView.propDecorators = { activeDate: [{ type: Input }], selected: [{ type: Input }], minDate: [{ type: Input }], maxDate: [{ type: Input }], dateFilter: [{ type: Input }], dateClass: [{ type: Input }], comparisonStart: [{ type: Input }], comparisonEnd: [{ type: Input }], selectedChange: [{ type: Output }], _userSelection: [{ type: Output }], activeDateChange: [{ type: Output }], _matCalendarBody: [{ type: ViewChild, args: [NgxMatCalendarBody,] }] }; if (false) { /** * @type {?} * @private */ NgxMatMonthView.prototype._rerenderSubscription; /** * @type {?} * @private */ NgxMatMonthView.prototype._activeDate; /** * @type {?} * @private */ NgxMatMonthView.prototype._selected; /** * @type {?} * @private */ NgxMatMonthView.prototype._minDate; /** * @type {?} * @private */ NgxMatMonthView.prototype._maxDate; /** * Function used to filter which dates are selectable. * @type {?} */ NgxMatMonthView.prototype.dateFilter; /** * Function that can be used to add custom CSS classes to dates. * @type {?} */ NgxMatMonthView.prototype.dateClass; /** * Start of the comparison range. * @type {?} */ NgxMatMonthView.prototype.comparisonStart; /** * End of the comparison range. * @type {?} */ NgxMatMonthView.prototype.comparisonEnd; /** * Emits when a new date is selected. * @type {?} */ NgxMatMonthView.prototype.selectedChange; /** * Emits when any date is selected. * @type {?} */ NgxMatMonthView.prototype._userSelection; /** * Emits when any date is activated. * @type {?} */ NgxMatMonthView.prototype.activeDateChange; /** * The body of calendar table * @type {?} */ NgxMatMonthView.prototype._matCalendarBody; /** * The label for this month (e.g. "January 2017"). * @type {?} */ NgxMatMonthView.prototype._monthLabel; /** * Grid of calendar cells representing the dates of the month. * @type {?} */ NgxMatMonthView.prototype._weeks; /** * The number of blank cells in the first row before the 1st of the month. * @type {?} */ NgxMatMonthView.prototype._firstWeekOffset; /** * Start value of the currently-shown date range. * @type {?} */ NgxMatMonthView.prototype._rangeStart; /** * End value of the currently-shown date range. * @type {?} */ NgxMatMonthView.prototype._rangeEnd; /** * Start value of the currently-shown comparison date range. * @type {?} */ NgxMatMonthView.prototype._comparisonRangeStart; /** * End value of the currently-shown comparison date range. * @type {?} */ NgxMatMonthView.prototype._comparisonRangeEnd; /** * Start of the preview range. * @type {?} */ NgxMatMonthView.prototype._previewStart; /** * End of the preview range. * @type {?} */ NgxMatMonthView.prototype._previewEnd; /** * Whether the user is currently selecting a range of dates. * @type {?} */ NgxMatMonthView.prototype._isRange; /** * The date of the month that today falls on. Null if today is in another month. * @type {?} */ NgxMatMonthView.prototype._todayDate; /** * The names of the weekdays. * @type {?} */ NgxMatMonthView.prototype._weekdays; /** * @type {?} * @private */ NgxMatMonthView.prototype._changeDetectorRef; /** * @type {?} * @private */ NgxMatMonthView.prototype._dateFormats; /** @type {?} */ NgxMatMonthView.prototype._dateAdapter; /** * @type {?} * @private */ NgxMatMonthView.prototype._dir; /** * @type {?} * @private */ NgxMatMonthView.prototype._rangeStrategy; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9udGgtdmlldy5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXRldGltZS1waWNrZXIvc3JjLyIsInNvdXJjZXMiOlsibGliL21vbnRoLXZpZXcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBUUEsT0FBTyxFQUNMLFVBQVUsRUFDVixHQUFHLEVBQ0gsS0FBSyxFQUNMLElBQUksRUFDSixVQUFVLEVBQ1YsU0FBUyxFQUNULE9BQU8sRUFDUCxXQUFXLEVBQ1gsUUFBUSxFQUNSLEtBQUssRUFDTCxNQUFNLEdBQ1AsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBRUwsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBQ0wsUUFBUSxFQUNSLE1BQU0sRUFDTixpQkFBaUIsRUFDakIsU0FBUyxHQUVWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUVqRCxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDekQsT0FBTyxFQUF5RCxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hJLE9BQU8sRUFBRSxvQkFBb0IsRUFBcUIsTUFBTSxxQkFBcUIsQ0FBQztBQUM5RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUscUNBQXFDLEVBQW9DLE1BQU0saUNBQWlDLENBQUM7QUFDMUgsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7O01BSTFELGFBQWEsR0FBRyxDQUFDOzs7Ozs7QUFjdkIsTUFBTSxPQUFPLGVBQWU7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QUEyQjs7Ozs7SUFRM0IsbUNBQTJCOzs7OztJQUczQixxQ0FBMEM7Ozs7O0lBRzFDLG9DQUE4RDs7Ozs7SUFHOUQsMENBQW1DOzs7OztJQUduQyx3Q0FBaUM7Ozs7O0lBR2pDLHlDQUF5Rjs7Ozs7SUFHekYseUNBQzBEOzs7OztJQUcxRCwyQ0FBNkU7Ozs7O0lBRzdFLDJDQUFvRTs7Ozs7SUFHcEUsc0NBQW9COzs7OztJQUdwQixpQ0FBK0I7Ozs7O0lBRy9CLDJDQUF5Qjs7Ozs7SUFHekIsc0NBQTJCOzs7OztJQUczQixvQ0FBeUI7Ozs7O0lBR3pCLGdEQUFxQzs7Ozs7SUFHckMsOENBQW1DOzs7OztJQUduQyx3Q0FBNkI7Ozs7O0lBRzdCLHNDQUEyQjs7Ozs7SUFHM0IsbUNBQWtCOzs7OztJQUdsQixxQ0FBMEI7Ozs7O0lBRzFCLG9DQUE0Qzs7Ozs7SUFFaEMsNkNBQTZDOzs7OztJQUM3Qyx1Q0FBaUY7O0lBQ2pGLHVDQUFxRDs7Ozs7SUFDckQsK0JBQXlDOzs7OztJQUN6Qyx5Q0FDZ0UiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtcbiAgRE9XTl9BUlJPVyxcbiAgRU5ELFxuICBFTlRFUixcbiAgSE9NRSxcbiAgTEVGVF9BUlJPVyxcbiAgUEFHRV9ET1dOLFxuICBQQUdFX1VQLFxuICBSSUdIVF9BUlJPVyxcbiAgVVBfQVJST1csXG4gIFNQQUNFLFxuICBFU0NBUEUsXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9rZXljb2Rlcyc7XG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBPcHRpb25hbCxcbiAgT3V0cHV0LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgVmlld0NoaWxkLFxuICBPbkRlc3Ryb3ksXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtEaXJlY3Rpb25hbGl0eX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2JpZGknO1xuXG5pbXBvcnQge1N1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge3N0YXJ0V2l0aH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRGF0ZVJhbmdlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcic7XG5pbXBvcnQgeyBOZ3hNYXRDYWxlbmRhckNlbGxDc3NDbGFzc2VzLCBOZ3hNYXRDYWxlbmRhclVzZXJFdmVudCwgTmd4TWF0Q2FsZW5kYXJCb2R5LCBOZ3hNYXRDYWxlbmRhckNlbGwgfSBmcm9tICcuL2NhbGVuZGFyLWJvZHknO1xuaW1wb3J0IHsgTkdYX01BVF9EQVRFX0ZPUk1BVFMsIE5neE1hdERhdGVGb3JtYXRzIH0gZnJvbSAnLi9jb3JlL2RhdGUtZm9ybWF0cyc7XG5pbXBvcnQgeyBOZ3hNYXREYXRlQWRhcHRlciB9IGZyb20gJy4vY29yZS9kYXRlLWFkYXB0ZXInO1xuaW1wb3J0IHsgTkdYX01BVF9EQVRFX1JBTkdFX1NFTEVDVElPTl9TVFJBVEVHWSwgTmd4TWF0RGF0ZVJhbmdlU2VsZWN0aW9uU3RyYXRlZ3kgfSBmcm9tICcuL2RhdGUtcmFuZ2Utc2VsZWN0aW9uLXN0cmF0ZWd5JztcbmltcG9ydCB7IGNyZWF0ZU1pc3NpbmdEYXRlSW1wbEVycm9yIH0gZnJvbSAnLi91dGlscy9kYXRlLXV0aWxzJztcblxuXG5cbmNvbnN0IERBWVNfUEVSX1dFRUsgPSA3O1xuXG5cbi8qKlxuICogQW4gaW50ZXJuYWwgY29tcG9uZW50IHVzZWQgdG8gZGlzcGxheSBhIHNpbmdsZSBtb250aCBpbiB0aGUgZGF0ZXBpY2tlci5cbiAqIEBkb2NzLXByaXZhdGVcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LW1hdC1tb250aC12aWV3JyxcbiAgdGVtcGxhdGVVcmw6ICdtb250aC12aWV3Lmh0bWwnLFxuICBleHBvcnRBczogJ25neE1hdE1vbnRoVmlldycsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIE5neE1hdE1vbnRoVmlldzxEPiBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgX3JlcmVuZGVyU3Vic2NyaXB0aW9uID0gU3Vic2NyaXB0aW9uLkVNUFRZO1xuXG4gIC8qKlxuICAgKiBUaGUgZGF0ZSB0byBkaXNwbGF5IGluIHRoaXMgbW9udGggdmlldyAoZXZlcnl0aGluZyBvdGhlciB0aGFuIHRoZSBtb250aCBhbmQgeWVhciBpcyBpZ25vcmVkKS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGdldCBhY3RpdmVEYXRlKCk6IEQgeyByZXR1cm4gdGhpcy5fYWN0aXZlRGF0ZTsgfVxuICBzZXQgYWN0aXZlRGF0ZSh2YWx1ZTogRCkge1xuICAgIGNvbnN0IG9sZEFjdGl2ZURhdGUgPSB0aGlzLl9hY3RpdmVEYXRlO1xuICAgIGNvbnN0IHZhbGlkRGF0ZSA9XG4gICAgICAgIHRoaXMuX2dldFZhbGlkRGF0ZU9yTnVsbCh0aGlzLl9kYXRlQWRhcHRlci5kZXNlcmlhbGl6ZSh2YWx1ZSkpIHx8IHRoaXMuX2RhdGVBZGFwdGVyLnRvZGF5KCk7XG4gICAgdGhpcy5fYWN0aXZlRGF0ZSA9IHRoaXMuX2RhdGVBZGFwdGVyLmNsYW1wRGF0ZSh2YWxpZERhdGUsIHRoaXMubWluRGF0ZSwgdGhpcy5tYXhEYXRlKTtcbiAgICBpZiAoIXRoaXMuX2hhc1NhbWVNb250aEFuZFllYXIob2xkQWN0aXZlRGF0ZSwgdGhpcy5fYWN0aXZlRGF0ZSkpIHtcbiAgICAgIHRoaXMuX2luaXQoKTtcbiAgICB9XG4gIH1cbiAgcHJpdmF0ZSBfYWN0aXZlRGF0ZTogRDtcblxuICAvKiogVGhlIGN1cnJlbnRseSBzZWxlY3RlZCBkYXRlLiAqL1xuICBASW5wdXQoKVxuICBnZXQgc2VsZWN0ZWQoKTogRGF0ZVJhbmdlPEQ+IHwgRCB8IG51bGwgeyByZXR1cm4gdGhpcy5fc2VsZWN0ZWQ7IH1cbiAgc2V0IHNlbGVjdGVkKHZhbHVlOiBEYXRlUmFuZ2U8RD4gfCBEIHwgbnVsbCkge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGVSYW5nZSkge1xuICAgICAgdGhpcy5fc2VsZWN0ZWQgPSB2YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fc2VsZWN0ZWQgPSB0aGlzLl9nZXRWYWxpZERhdGVPck51bGwodGhpcy5fZGF0ZUFkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zZXRSYW5nZXModGhpcy5fc2VsZWN0ZWQpO1xuICB9XG4gIHByaXZhdGUgX3NlbGVjdGVkOiBEYXRlUmFuZ2U8RD4gfCBEIHwgbnVsbDtcblxuICAvKiogVGhlIG1pbmltdW0gc2VsZWN0YWJsZSBkYXRlLiAqL1xuICBASW5wdXQoKVxuICBnZXQgbWluRGF0ZSgpOiBEIHwgbnVsbCB7IHJldHVybiB0aGlzLl9taW5EYXRlOyB9XG4gIHNldCBtaW5EYXRlKHZhbHVlOiBEIHwgbnVsbCkge1xuICAgIHRoaXMuX21pbkRhdGUgPSB0aGlzLl9nZXRWYWxpZERhdGVPck51bGwodGhpcy5fZGF0ZUFkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgfVxuICBwcml2YXRlIF9taW5EYXRlOiBEIHwgbnVsbDtcblxuICAvKiogVGhlIG1heGltdW0gc2VsZWN0YWJsZSBkYXRlLiAqL1xuICBASW5wdXQoKVxuICBnZXQgbWF4RGF0ZSgpOiBEIHwgbnVsbCB7IHJldHVybiB0aGlzLl9tYXhEYXRlOyB9XG4gIHNldCBtYXhEYXRlKHZhbHVlOiBEIHwgbnVsbCkge1xuICAgIHRoaXMuX21heERhdGUgPSB0aGlzLl9nZXRWYWxpZERhdGVPck51bGwodGhpcy5fZGF0ZUFkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgfVxuICBwcml2YXRlIF9tYXhEYXRlOiBEIHwgbnVsbDtcblxuICAvKiogRnVuY3Rpb24gdXNlZCB0byBmaWx0ZXIgd2hpY2ggZGF0ZXMgYXJlIHNlbGVjdGFibGUuICovXG4gIEBJbnB1dCgpIGRhdGVGaWx0ZXI6IChkYXRlOiBEKSA9PiBib29sZWFuO1xuXG4gIC8qKiBGdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkIHRvIGFkZCBjdXN0b20gQ1NTIGNsYXNzZXMgdG8gZGF0ZXMuICovXG4gIEBJbnB1dCgpIGRhdGVDbGFzczogKGRhdGU6IEQpID0+IE5neE1hdENhbGVuZGFyQ2VsbENzc0NsYXNzZXM7XG5cbiAgLyoqIFN0YXJ0IG9mIHRoZSBjb21wYXJpc29uIHJhbmdlLiAqL1xuICBASW5wdXQoKSBjb21wYXJpc29uU3RhcnQ6IEQgfCBudWxsO1xuXG4gIC8qKiBFbmQgb2YgdGhlIGNvbXBhcmlzb24gcmFuZ2UuICovXG4gIEBJbnB1dCgpIGNvbXBhcmlzb25FbmQ6IEQgfCBudWxsO1xuXG4gIC8qKiBFbWl0cyB3aGVuIGEgbmV3IGRhdGUgaXMgc2VsZWN0ZWQuICovXG4gIEBPdXRwdXQoKSByZWFkb25seSBzZWxlY3RlZENoYW5nZTogRXZlbnRFbWl0dGVyPEQgfCBudWxsPiA9IG5ldyBFdmVudEVtaXR0ZXI8RCB8IG51bGw+KCk7XG5cbiAgLyoqIEVtaXRzIHdoZW4gYW55IGRhdGUgaXMgc2VsZWN0ZWQuICovXG4gIEBPdXRwdXQoKSByZWFkb25seSBfdXNlclNlbGVjdGlvbjogRXZlbnRFbWl0dGVyPE5neE1hdENhbGVuZGFyVXNlckV2ZW50PEQgfCBudWxsPj4gPVxuICAgICAgbmV3IEV2ZW50RW1pdHRlcjxOZ3hNYXRDYWxlbmRhclVzZXJFdmVudDxEIHwgbnVsbD4+KCk7XG5cbiAgLyoqIEVtaXRzIHdoZW4gYW55IGRhdGUgaXMgYWN0aXZhdGVkLiAqL1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgYWN0aXZlRGF0ZUNoYW5nZTogRXZlbnRFbWl0dGVyPEQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxEPigpO1xuXG4gIC8qKiBUaGUgYm9keSBvZiBjYWxlbmRhciB0YWJsZSAqL1xuICBAVmlld0NoaWxkKE5neE1hdENhbGVuZGFyQm9keSkgX21hdENhbGVuZGFyQm9keTogTmd4TWF0Q2FsZW5kYXJCb2R5O1xuXG4gIC8qKiBUaGUgbGFiZWwgZm9yIHRoaXMgbW9udGggKGUuZy4gXCJKYW51YXJ5IDIwMTdcIikuICovXG4gIF9tb250aExhYmVsOiBzdHJpbmc7XG5cbiAgLyoqIEdyaWQgb2YgY2FsZW5kYXIgY2VsbHMgcmVwcmVzZW50aW5nIHRoZSBkYXRlcyBvZiB0aGUgbW9udGguICovXG4gIF93ZWVrczogTmd4TWF0Q2FsZW5kYXJDZWxsW11bXTtcblxuICAvKiogVGhlIG51bWJlciBvZiBibGFuayBjZWxscyBpbiB0aGUgZmlyc3Qgcm93IGJlZm9yZSB0aGUgMXN0IG9mIHRoZSBtb250aC4gKi9cbiAgX2ZpcnN0V2Vla09mZnNldDogbnVtYmVyO1xuXG4gIC8qKiBTdGFydCB2YWx1ZSBvZiB0aGUgY3VycmVudGx5LXNob3duIGRhdGUgcmFuZ2UuICovXG4gIF9yYW5nZVN0YXJ0OiBudW1iZXIgfCBudWxsO1xuXG4gIC8qKiBFbmQgdmFsdWUgb2YgdGhlIGN1cnJlbnRseS1zaG93biBkYXRlIHJhbmdlLiAqL1xuICBfcmFuZ2VFbmQ6IG51bWJlciB8IG51bGw7XG5cbiAgLyoqIFN0YXJ0IHZhbHVlIG9mIHRoZSBjdXJyZW50bHktc2hvd24gY29tcGFyaXNvbiBkYXRlIHJhbmdlLiAqL1xuICBfY29tcGFyaXNvblJhbmdlU3RhcnQ6IG51bWJlciB8IG51bGw7XG5cbiAgLyoqIEVuZCB2YWx1ZSBvZiB0aGUgY3VycmVudGx5LXNob3duIGNvbXBhcmlzb24gZGF0ZSByYW5nZS4gKi9cbiAgX2NvbXBhcmlzb25SYW5nZUVuZDogbnVtYmVyIHwgbnVsbDtcblxuICAvKiogU3RhcnQgb2YgdGhlIHByZXZpZXcgcmFuZ2UuICovXG4gIF9wcmV2aWV3U3RhcnQ6IG51bWJlciB8IG51bGw7XG5cbiAgLyoqIEVuZCBvZiB0aGUgcHJldmlldyByYW5nZS4gKi9cbiAgX3ByZXZpZXdFbmQ6IG51bWJlciB8IG51bGw7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIHVzZXIgaXMgY3VycmVudGx5IHNlbGVjdGluZyBhIHJhbmdlIG9mIGRhdGVzLiAqL1xuICBfaXNSYW5nZTogYm9vbGVhbjtcblxuICAvKiogVGhlIGRhdGUgb2YgdGhlIG1vbnRoIHRoYXQgdG9kYXkgZmFsbHMgb24uIE51bGwgaWYgdG9kYXkgaXMgaW4gYW5vdGhlciBtb250aC4gKi9cbiAgX3RvZGF5RGF0ZTogbnVtYmVyIHwgbnVsbDtcblxuICAvKiogVGhlIG5hbWVzIG9mIHRoZSB3ZWVrZGF5cy4gKi9cbiAgX3dlZWtkYXlzOiB7bG9uZzogc3RyaW5nLCBuYXJyb3c6IHN0cmluZ31bXTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgICAgICAgIEBPcHRpb25hbCgpIEBJbmplY3QoTkdYX01BVF9EQVRFX0ZPUk1BVFMpIHByaXZhdGUgX2RhdGVGb3JtYXRzOiBOZ3hNYXREYXRlRm9ybWF0cyxcbiAgICAgICAgICAgICAgQE9wdGlvbmFsKCkgcHVibGljIF9kYXRlQWRhcHRlcjogTmd4TWF0RGF0ZUFkYXB0ZXI8RD4sXG4gICAgICAgICAgICAgIEBPcHRpb25hbCgpIHByaXZhdGUgX2Rpcj86IERpcmVjdGlvbmFsaXR5LFxuICAgICAgICAgICAgICBASW5qZWN0KE5HWF9NQVRfREFURV9SQU5HRV9TRUxFQ1RJT05fU1RSQVRFR1kpIEBPcHRpb25hbCgpXG4gICAgICAgICAgICAgICAgICBwcml2YXRlIF9yYW5nZVN0cmF0ZWd5PzogTmd4TWF0RGF0ZVJhbmdlU2VsZWN0aW9uU3RyYXRlZ3k8RD4pIHtcbiAgICBpZiAoIXRoaXMuX2RhdGVBZGFwdGVyKSB7XG4gICAgICB0aHJvdyBjcmVhdGVNaXNzaW5nRGF0ZUltcGxFcnJvcignTmd4TWF0RGF0ZUFkYXB0ZXInKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLl9kYXRlRm9ybWF0cykge1xuICAgICAgdGhyb3cgY3JlYXRlTWlzc2luZ0RhdGVJbXBsRXJyb3IoJ05HWF9NQVRfREFURV9GT1JNQVRTJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fYWN0aXZlRGF0ZSA9IHRoaXMuX2RhdGVBZGFwdGVyLnRvZGF5KCk7XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XG4gICAgdGhpcy5fcmVyZW5kZXJTdWJzY3JpcHRpb24gPSB0aGlzLl9kYXRlQWRhcHRlci5sb2NhbGVDaGFuZ2VzXG4gICAgICAucGlwZShzdGFydFdpdGgobnVsbCkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuX2luaXQoKSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLl9yZXJlbmRlclN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgLyoqIEhhbmRsZXMgd2hlbiBhIG5ldyBkYXRlIGlzIHNlbGVjdGVkLiAqL1xuICBfZGF0ZVNlbGVjdGVkKGV2ZW50OiBOZ3hNYXRDYWxlbmRhclVzZXJFdmVudDxudW1iZXI+KSB7XG4gICAgY29uc3QgZGF0ZSA9IGV2ZW50LnZhbHVlO1xuICAgIGNvbnN0IHNlbGVjdGVkWWVhciA9IHRoaXMuX2RhdGVBZGFwdGVyLmdldFllYXIodGhpcy5hY3RpdmVEYXRlKTtcbiAgICBjb25zdCBzZWxlY3RlZE1vbnRoID0gdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0TW9udGgodGhpcy5hY3RpdmVEYXRlKTtcbiAgICBjb25zdCBzZWxlY3RlZERhdGUgPSB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKHNlbGVjdGVkWWVhciwgc2VsZWN0ZWRNb250aCwgZGF0ZSk7XG4gICAgbGV0IHJhbmdlU3RhcnREYXRlOiBudW1iZXIgfCBudWxsO1xuICAgIGxldCByYW5nZUVuZERhdGU6IG51bWJlciB8IG51bGw7XG5cbiAgICBpZiAodGhpcy5fc2VsZWN0ZWQgaW5zdGFuY2VvZiBEYXRlUmFuZ2UpIHtcbiAgICAgIHJhbmdlU3RhcnREYXRlID0gdGhpcy5fZ2V0RGF0ZUluQ3VycmVudE1vbnRoKHRoaXMuX3NlbGVjdGVkLnN0YXJ0KTtcbiAgICAgIHJhbmdlRW5kRGF0ZSA9IHRoaXMuX2dldERhdGVJbkN1cnJlbnRNb250aCh0aGlzLl9zZWxlY3RlZC5lbmQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByYW5nZVN0YXJ0RGF0ZSA9IHJhbmdlRW5kRGF0ZSA9IHRoaXMuX2dldERhdGVJbkN1cnJlbnRNb250aCh0aGlzLl9zZWxlY3RlZCk7XG4gICAgfVxuXG4gICAgaWYgKHJhbmdlU3RhcnREYXRlICE9PSBkYXRlIHx8IHJhbmdlRW5kRGF0ZSAhPT0gZGF0ZSkge1xuICAgICAgdGhpcy5zZWxlY3RlZENoYW5nZS5lbWl0KHNlbGVjdGVkRGF0ZSk7XG4gICAgfVxuXG4gICAgdGhpcy5fdXNlclNlbGVjdGlvbi5lbWl0KHt2YWx1ZTogc2VsZWN0ZWREYXRlLCBldmVudDogZXZlbnQuZXZlbnR9KTtcbiAgfVxuXG4gIC8qKiBIYW5kbGVzIGtleWRvd24gZXZlbnRzIG9uIHRoZSBjYWxlbmRhciBib2R5IHdoZW4gY2FsZW5kYXIgaXMgaW4gbW9udGggdmlldy4gKi9cbiAgX2hhbmRsZUNhbGVuZGFyQm9keUtleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBUT0RPKG1tYWxlcmJhKTogV2UgY3VycmVudGx5IGFsbG93IGtleWJvYXJkIG5hdmlnYXRpb24gdG8gZGlzYWJsZWQgZGF0ZXMsIGJ1dCBqdXN0IHByZXZlbnRcbiAgICAvLyBkaXNhYmxlZCBvbmVzIGZyb20gYmVpbmcgc2VsZWN0ZWQuIFRoaXMgbWF5IG5vdCBiZSBpZGVhbCwgd2Ugc2hvdWxkIGxvb2sgaW50byB3aGV0aGVyXG4gICAgLy8gbmF2aWdhdGlvbiBzaG91bGQgc2tpcCBvdmVyIGRpc2FibGVkIGRhdGVzLCBhbmQgaWYgc28sIGhvdyB0byBpbXBsZW1lbnQgdGhhdCBlZmZpY2llbnRseS5cblxuICAgIGNvbnN0IG9sZEFjdGl2ZURhdGUgPSB0aGlzLl9hY3RpdmVEYXRlO1xuICAgIGNvbnN0IGlzUnRsID0gdGhpcy5faXNSdGwoKTtcblxuICAgIH