fundamental-ngx
Version:
SAP Fiori Fundamentals, implemented in Angular
1,394 lines (1,393 loc) • 187 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, EventEmitter, Input, Output, HostListener, ElementRef, forwardRef, ChangeDetectorRef, HostBinding, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { CalendarI18n } from './i18n/calendar-i18n';
import { CalendarI18nLabels } from './i18n/calendar-i18n-labels';
import { DateFormatParser } from './format/date-parser';
/**
* @record
*/
export function CalendarDay() { }
if (false) {
/** @type {?} */
CalendarDay.prototype.date;
/** @type {?|undefined} */
CalendarDay.prototype.day;
/** @type {?|undefined} */
CalendarDay.prototype.weekDay;
/** @type {?|undefined} */
CalendarDay.prototype.monthStatus;
/** @type {?|undefined} */
CalendarDay.prototype.disabled;
/** @type {?|undefined} */
CalendarDay.prototype.blocked;
/** @type {?|undefined} */
CalendarDay.prototype.selected;
/** @type {?|undefined} */
CalendarDay.prototype.selectedFirst;
/** @type {?|undefined} */
CalendarDay.prototype.selectedRange;
/** @type {?|undefined} */
CalendarDay.prototype.selectedLast;
/** @type {?|undefined} */
CalendarDay.prototype.today;
/** @type {?|undefined} */
CalendarDay.prototype.isTabIndexed;
/** @type {?|undefined} */
CalendarDay.prototype.ariaLabel;
}
/**
* @record
*/
export function EmittedDate() { }
if (false) {
/** @type {?|undefined} */
EmittedDate.prototype.selectedDay;
/** @type {?|undefined} */
EmittedDate.prototype.selectedFirstDay;
/** @type {?|undefined} */
EmittedDate.prototype.selectedLastDay;
}
/** @type {?} */
var calendarUniqueId = 0;
/**
* Calendar component used for selecting dates, typically used by the DatePicker and DateTimePicker components.
* Supports the Angular forms module, enabling form validity, ngModel, etc.
*/
var CalendarComponent = /** @class */ (function () {
function CalendarComponent(eRef, cd, calendarI18nLabels, calendarI18n, dateAdapter) {
this.eRef = eRef;
this.cd = cd;
this.calendarI18nLabels = calendarI18nLabels;
this.calendarI18n = calendarI18n;
this.dateAdapter = dateAdapter;
/**
* @hidden Used to check if this is the calendar being initialized. Internal use.
*/
this.init = false;
/**
* @hidden Applies the fd-calendar class to this component. Internal use.
*/
this.fdCalendarClass = true;
/**
* Id of the calendar. If none is provided, one will be generated.
*/
this.id = 'fd-calendar-' + calendarUniqueId++;
/**
* The type of calendar, 'single' for single date selection or 'range' for a range of dates.
*/
this.calType = 'single';
/**
* The day of the week the calendar should start on. 0 represents Sunday, 1 is Monday, 2 is Tuesday, and so on.
*/
this.startingDayOfWeek = 0;
/**
* Fired when the date input value is invalid.
*/
this.isInvalidDateInput = new EventEmitter();
/**
* Whether wants to allow escape focus, otherwise it resets on beginning.
*/
this.allowFocusEscape = false;
/**
* @hidden Whether the date is invalid. Internal use.
*/
this.invalidDate = false;
/**
* @hidden Whether to show the month selection grid on the calendar. Internal use.
*/
this.showCalendarMonths = false;
/**
* @hidden Whether to show the year selection grid on the calendar. Internal use.
*/
this.showCalendarYears = false;
/**
* @hidden Whether to show the date selection grid on the calendar. Internal use.
*/
this.showCalendarDates = true;
/**
* @hidden The typical number of days in each month. Internal use.
*/
this.daysPerMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
/**
* @hidden The displayed grid of calendar days. Internal use.
*/
this.calendarGrid = [];
/**
* @hidden The years to display in the year selection grid. Internal use.
*/
this.calendarYearsList = [];
/**
* @hidden Today's date. Internal use.
*/
this.today = new Date();
/**
* @hidden Today's month. Internal use.
*/
this.todayMonth = this.today.getMonth();
/**
* @hidden Today's year. Internal use.
*/
this.todayYear = this.today.getFullYear();
/**
* @hidden Date used to navigate the calendar. Not to be confused with selectedDay which is the ngModel. Internal use.
*/
this.date = new Date();
/**
* @hidden Month used to navigate the calendar.Internal use.
*/
this.month = this.date.getMonth();
/**
* @hidden Year used to navigate the calendar. Internal use.
*/
this.year = this.date.getFullYear();
/**
* @hidden Day of month used to navigate the calendar. Internal use.
*/
this.day = this.date.getDate();
/**
* @hidden The first year to be displayed in the list of selectable years. Internal use.
*/
this.firstYearCalendarList = this.year;
/**
* @hidden The first year to be displayed in the list of selectable years. Internal use.
*/
this.selectCounter = 0;
/**
* The currently selected CalendarDay model.
*/
this.selectedDay = {
date: null
};
/**
* Fired when a new date is selected.
*/
this.selectedDayChange = new EventEmitter();
/**
* The currently selected first CalendarDay in a range type calendar.
*/
this.selectedRangeFirst = {
date: null
};
/**
* Fired when the user selects a new first date in a range of dates is selected.
*/
this.selectedRangeFirstChange = new EventEmitter();
/**
* The currently selected last CalendarDay in a range type calendar.
*/
this.selectedRangeLast = {
date: null
};
/**
* Fired when the user selects a new last date in a range of dates is selected.
*/
this.selectedRangeLastChange = new EventEmitter();
/**
* @hidden The date that gets emitted to the datePicker when the select day changes on the calendar. Internal use.
*/
this.emittedDate = {
selectedDay: this.selectedDay,
selectedFirstDay: this.selectedRangeFirst,
selectedLastDay: this.selectedRangeLast
};
/**
* Fired when the calendar is closed.
*/
this.closeCalendar = new EventEmitter();
/**
* Function used to disable certain dates in the calendar.
* @param d Date
*/
this.disableFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to disable certain dates in the calendar for the range start selection.
* @param d Date
*/
this.disableRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to disable certain dates in the calendar for the range end selection.
* @param d Date
*/
this.disableRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to block certain dates in the calendar for the range start selection.
* @param d Date
*/
this.blockRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to block certain dates in the calendar for the range end selection.
* @param d Date
*/
this.blockRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to block certain dates in the calendar.
* @param d Date
*/
this.blockFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* @hidden
*/
this.onChange = (/**
* @return {?}
*/
function () { });
/**
* @hidden
*/
this.onTouched = (/**
* @return {?}
*/
function () { });
/**
* @hidden
*/
this.determineDaysInMonth = (/**
* @param {?} month
* @param {?} year
* @return {?}
*/
function (month, year) {
if (month === 1) {
if ((year % 100 !== 0 && year % 4 === 0) || year % 400 === 0) {
return 29;
}
else {
return this.daysPerMonth[month];
}
}
else {
return this.daysPerMonth[month];
}
});
}
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.setWeekDaysOrder = /**
* @hidden
* @return {?}
*/
function () {
this.weekDays = this.calendarI18n.getAllShortWeekdays().map((/**
* @param {?} item
* @return {?}
*/
function (item) { return item[0]; }));
if (this.startingDayOfWeek <= 6 && this.startingDayOfWeek >= 0) {
for (var i = this.startingDayOfWeek; i > 0; i--) {
this.weekDays.push(this.weekDays.shift());
}
}
};
/** @hidden */
/**
* @hidden
* @param {?} calendarMonth
* @return {?}
*/
CalendarComponent.prototype.getPreviousMonthDays = /**
* @hidden
* @param {?} calendarMonth
* @return {?}
*/
function (calendarMonth) {
// Previous month days
/** @type {?} */
var prevMonthLastDate;
this.setWeekDaysOrder();
prevMonthLastDate = new Date(this.date.getFullYear(), this.date.getMonth(), 0);
/** @type {?} */
var prevMonth = prevMonthLastDate.getMonth();
/** @type {?} */
var prevMonthYear = prevMonthLastDate.getFullYear();
/** @type {?} */
var prevMonthLastDay = prevMonthLastDate.getDate();
/** @type {?} */
var prevMonthLastWeekDay = prevMonthLastDate.getDay() - this.startingDayOfWeek;
if (prevMonthLastWeekDay < 6) {
while (prevMonthLastWeekDay >= 0) {
/** @type {?} */
var prevMonthDay = prevMonthLastDay - prevMonthLastWeekDay;
/** @type {?} */
var calDate = new Date(prevMonthYear, prevMonth, prevMonthDay);
/** @type {?} */
var previousMonthCalendarDay = {
date: calDate,
day: calDate.getDate(),
weekDay: calDate.getDay(),
monthStatus: 'previous',
disabled: this.disableFunction(calDate),
blocked: this.blockFunction(calDate),
selected: (this.selectedDay.date && calDate.toDateString() === this.selectedDay.date.toDateString()) ||
(this.selectedRangeFirst.date &&
calDate.toDateString() === this.selectedRangeFirst.date.toDateString()) ||
(this.selectedRangeLast.date &&
calDate.toDateString() === this.selectedRangeLast.date.toDateString()),
selectedFirst: this.selectedRangeFirst.date &&
calDate.toDateString() === this.selectedRangeFirst.date.toDateString(),
selectedLast: this.selectedRangeLast.date &&
calDate.toDateString() === this.selectedRangeLast.date.toDateString(),
selectedRange: this.selectedRangeFirst.date &&
calDate.getTime() > this.selectedRangeFirst.date.getTime() &&
this.selectedRangeLast.date &&
calDate.getTime() < this.selectedRangeLast.date.getTime(),
ariaLabel: this.calendarI18n.getDayAriaLabel(calDate)
};
if (this.selectCounter === 0) {
if (this.disableRangeStartFunction && !previousMonthCalendarDay.disabled) {
previousMonthCalendarDay.disabled = this.disableRangeStartFunction(calDate);
}
if (this.blockRangeStartFunction && !previousMonthCalendarDay.blocked) {
previousMonthCalendarDay.blocked = this.blockRangeStartFunction(calDate);
}
}
else if (this.selectCounter === 1) {
if (this.disableRangeEndFunction && !previousMonthCalendarDay.disabled) {
previousMonthCalendarDay.disabled = this.disableRangeEndFunction(calDate);
}
if (this.blockRangeEndFunction && !previousMonthCalendarDay.blocked) {
previousMonthCalendarDay.blocked = this.blockRangeEndFunction(calDate);
}
}
calendarMonth.push(previousMonthCalendarDay);
prevMonthLastWeekDay--;
}
}
return calendarMonth;
};
/** @hidden */
/**
* @hidden
* @param {?} calendarMonth
* @return {?}
*/
CalendarComponent.prototype.getCurrentMonthDays = /**
* @hidden
* @param {?} calendarMonth
* @return {?}
*/
function (calendarMonth) {
/** @type {?} */
var numOfDaysInCurrentMonth = this.determineDaysInMonth(this.month, this.year);
// Current month days
/** @type {?} */
var foundSelected = false;
for (var d = 1; d <= numOfDaysInCurrentMonth; d++) {
/** @type {?} */
var calDate = new Date(this.date.getFullYear(), this.date.getMonth(), d);
/** @type {?} */
var currMonthCalendarDay = {
date: calDate,
day: calDate.getDate(),
weekDay: calDate.getDay(),
monthStatus: 'current',
disabled: this.disableFunction(calDate),
blocked: this.blockFunction(calDate),
selected: (this.selectedDay.date && calDate.toDateString() === this.selectedDay.date.toDateString()) ||
(this.selectedRangeFirst.date &&
calDate.toDateString() === this.selectedRangeFirst.date.toDateString()) ||
(this.selectedRangeLast.date &&
calDate.toDateString() === this.selectedRangeLast.date.toDateString()),
selectedFirst: this.selectedRangeFirst.date &&
calDate.toDateString() === this.selectedRangeFirst.date.toDateString(),
selectedLast: this.selectedRangeLast.date &&
calDate.toDateString() === this.selectedRangeLast.date.toDateString(),
selectedRange: this.selectedRangeFirst.date &&
calDate.getTime() > this.selectedRangeFirst.date.getTime() &&
this.selectedRangeLast.date &&
calDate.getTime() < this.selectedRangeLast.date.getTime(),
today: calDate.toDateString() === this.today.toDateString(),
isTabIndexed: false,
ariaLabel: this.calendarI18n.getDayAriaLabel(calDate)
};
if (this.selectCounter === 0 || this.selectCounter === 2) {
if (this.disableRangeStartFunction && !currMonthCalendarDay.disabled) {
currMonthCalendarDay.disabled = this.disableRangeStartFunction(calDate);
}
if (this.blockRangeStartFunction && !currMonthCalendarDay.blocked) {
currMonthCalendarDay.blocked = this.blockRangeStartFunction(calDate);
}
}
else if (this.selectCounter === 1) {
if (this.disableRangeEndFunction && !currMonthCalendarDay.disabled) {
currMonthCalendarDay.disabled = this.disableRangeEndFunction(calDate);
}
if (this.blockRangeEndFunction && !currMonthCalendarDay.blocked) {
currMonthCalendarDay.blocked = this.blockRangeEndFunction(calDate);
}
}
// if a day is selected, it should be tab indexed
if (currMonthCalendarDay.selected) {
foundSelected = true;
currMonthCalendarDay.isTabIndexed = true;
}
calendarMonth.push(currMonthCalendarDay);
}
if (!foundSelected) {
/** @type {?} */
var foundToday = false;
for (var d = 0; d < numOfDaysInCurrentMonth; d++) {
// if no day is selected, tab index today
if (calendarMonth[d] && calendarMonth[d].today) {
foundToday = true;
calendarMonth[d].isTabIndexed = true;
}
}
// if today isn't present on the calendarGrid, tab index the first day
if (!foundToday) {
calendarMonth[0].isTabIndexed = true;
}
}
return calendarMonth;
};
/** @hidden */
/**
* @hidden
* @param {?} calendarMonth
* @return {?}
*/
CalendarComponent.prototype.getNextMonthDays = /**
* @hidden
* @param {?} calendarMonth
* @return {?}
*/
function (calendarMonth) {
// Next month days
/** @type {?} */
var nextMonthDisplayedDays = 0;
// The calendar grid can have either 5 (35 days) or 6 (42 days) weeks
// depending on the week day of the first day of the current month
// and the number of days in the current month
if (calendarMonth.length > 35) {
nextMonthDisplayedDays = 42 - calendarMonth.length;
}
else {
nextMonthDisplayedDays = 35 - calendarMonth.length;
}
for (var nextD = 1; nextD <= nextMonthDisplayedDays; nextD++) {
/** @type {?} */
var nextMonthFirstDate = void 0;
if (this.date.getMonth() === 11) {
nextMonthFirstDate = new Date(this.date.getFullYear() + 1, 0, 1);
}
else {
nextMonthFirstDate = new Date(this.date.getFullYear(), this.date.getMonth() + 1, 1);
}
/** @type {?} */
var nextMonth = nextMonthFirstDate.getMonth();
/** @type {?} */
var nextMonthYear = nextMonthFirstDate.getFullYear();
/** @type {?} */
var calDate = new Date(nextMonthYear, nextMonth, nextD);
/** @type {?} */
var nextMonthCalendarDay = {
date: calDate,
day: calDate.getDate(),
weekDay: calDate.getDay(),
monthStatus: 'next',
disabled: this.disableFunction(calDate),
blocked: this.blockFunction(calDate),
selected: (this.selectedDay.date && calDate.toDateString() === this.selectedDay.date.toDateString()) ||
(this.selectedRangeFirst.date &&
calDate.toDateString() === this.selectedRangeFirst.date.toDateString()) ||
(this.selectedRangeLast.date &&
calDate.toDateString() === this.selectedRangeLast.date.toDateString()),
selectedFirst: this.selectedRangeFirst.date &&
calDate.toDateString() === this.selectedRangeFirst.date.toDateString(),
selectedLast: this.selectedRangeLast.date &&
calDate.toDateString() === this.selectedRangeLast.date.toDateString(),
selectedRange: this.selectedRangeFirst.date &&
calDate.getTime() > this.selectedRangeFirst.date.getTime() &&
this.selectedRangeLast.date &&
calDate.getTime() < this.selectedRangeLast.date.getTime(),
ariaLabel: this.calendarI18n.getDayAriaLabel(calDate)
};
if (this.selectCounter === 0) {
if (this.disableRangeStartFunction && !nextMonthCalendarDay.disabled) {
nextMonthCalendarDay.disabled = this.disableRangeStartFunction(calDate);
}
if (this.blockRangeStartFunction && !nextMonthCalendarDay.blocked) {
nextMonthCalendarDay.blocked = this.blockRangeStartFunction(calDate);
}
}
else if (this.selectCounter === 1) {
if (this.disableRangeEndFunction && !nextMonthCalendarDay.disabled) {
nextMonthCalendarDay.disabled = this.disableRangeEndFunction(calDate);
}
if (this.blockRangeEndFunction && !nextMonthCalendarDay.blocked) {
nextMonthCalendarDay.blocked = this.blockRangeEndFunction(calDate);
}
}
calendarMonth.push(nextMonthCalendarDay);
}
return calendarMonth;
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.populateCalendar = /**
* @hidden
* @return {?}
*/
function () {
/** @type {?} */
var calendarMonth = [];
calendarMonth = this.getPreviousMonthDays(calendarMonth);
calendarMonth = this.getCurrentMonthDays(calendarMonth);
calendarMonth = this.getNextMonthDays(calendarMonth);
return calendarMonth;
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.constructCalendar = /**
* @hidden
* @return {?}
*/
function () {
/** @type {?} */
var calendarDays = this.populateCalendar();
/** @type {?} */
var calendarGrid = [];
while (calendarDays.length > 0) {
calendarGrid.push(calendarDays.splice(0, 7));
}
this.calendarGrid = calendarGrid;
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.refreshSelected = /**
* @hidden
* @return {?}
*/
function () {
var _this = this;
this.calendarGrid.forEach((/**
* @param {?} grid
* @return {?}
*/
function (grid) {
grid.forEach((/**
* @param {?} day
* @return {?}
*/
function (day) {
day.selected =
(_this.selectedDay.date && day.date && day.date.toDateString() === _this.selectedDay.date.toDateString()) ||
(_this.selectedRangeFirst.date &&
day.date.toDateString() === _this.selectedRangeFirst.date.toDateString()) ||
(_this.selectedRangeLast.date &&
day.date.toDateString() === _this.selectedRangeLast.date.toDateString());
day.selectedFirst =
_this.selectedRangeFirst.date && day.date &&
day.date.toDateString() === _this.selectedRangeFirst.date.toDateString();
day.selectedLast =
_this.selectedRangeLast.date && day.date &&
day.date.toDateString() === _this.selectedRangeLast.date.toDateString();
day.selectedRange =
_this.selectedRangeFirst.date &&
day.date.getTime() > _this.selectedRangeFirst.date.getTime() &&
_this.selectedRangeLast.date &&
day.date.getTime() < _this.selectedRangeLast.date.getTime();
}));
}));
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.updateDatePickerInputEmitter = /**
* @hidden
* @return {?}
*/
function () {
if (this.calType === 'single') {
this.emittedDate.selectedDay = this.selectedDay;
}
else {
this.emittedDate.selectedFirstDay = this.selectedRangeFirst;
this.emittedDate.selectedLastDay = this.selectedRangeLast;
}
if (this.dateFromDatePicker) {
this.dateFromDatePicker.next(this.emittedDate);
}
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.constructCalendarYearsList = /**
* @hidden
* @return {?}
*/
function () {
this.calendarYearsList = [];
for (var y = 0; y < 12; y++) {
this.calendarYearsList.push(this.firstYearCalendarList + y);
}
};
/** @hidden */
/**
* @hidden
* @param {?} year
* @param {?} i
* @return {?}
*/
CalendarComponent.prototype.getYearTabIndex = /**
* @hidden
* @param {?} year
* @param {?} i
* @return {?}
*/
function (year, i) {
var _this = this;
/** @type {?} */
var retVal = -1;
// tab index currently selected year
if (year === this.year) {
retVal = 0;
}
else {
// if no year on the calendarYearsList is selected, tab index the first
/** @type {?} */
var foundYear_1 = false;
this.calendarYearsList.forEach((/**
* @param {?} yearFromList
* @return {?}
*/
function (yearFromList) {
if (_this.year === yearFromList) {
foundYear_1 = true;
}
}));
if (!foundYear_1) {
if (i === 0) {
retVal = 0;
}
}
}
return retVal;
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.goToPreviousMonth = /**
* @hidden
* @return {?}
*/
function () {
this.setCurrentMonth(this.date.getMonth() - 1);
this.selectedMonth = this.month;
this.constructCalendar();
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.goToNextMonth = /**
* @hidden
* @return {?}
*/
function () {
this.setCurrentMonth(this.date.getMonth() + 1);
this.selectedMonth = this.month;
this.constructCalendar();
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.loadNextYearsList = /**
* @hidden
* @return {?}
*/
function () {
this.calendarYearsList = [];
this.firstYearCalendarList += 12;
this.constructCalendarYearsList();
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.loadPrevYearsList = /**
* @hidden
* @return {?}
*/
function () {
this.calendarYearsList = [];
this.firstYearCalendarList -= 12;
this.constructCalendarYearsList();
};
/**
* Function for selecting a date on the calendar. Typically called when a date is clicked, but can also be called programmatically.
* @param day CalendarDay object to be selected.
* @param formEvent If this function should emit an ngModelChange.
* @param event Event passed with this function call, typically the mouse click when selecting from the calendar grid.
* @param closeCalendar If the calendar should be closed when a date is selected, used with DatePicker and DateTimePicker.
*/
/**
* Function for selecting a date on the calendar. Typically called when a date is clicked, but can also be called programmatically.
* @param {?} day CalendarDay object to be selected.
* @param {?=} formEvent If this function should emit an ngModelChange.
* @param {?=} event Event passed with this function call, typically the mouse click when selecting from the calendar grid.
* @param {?=} closeCalendar If the calendar should be closed when a date is selected, used with DatePicker and DateTimePicker.
* @return {?}
*/
CalendarComponent.prototype.selectDate = /**
* Function for selecting a date on the calendar. Typically called when a date is clicked, but can also be called programmatically.
* @param {?} day CalendarDay object to be selected.
* @param {?=} formEvent If this function should emit an ngModelChange.
* @param {?=} event Event passed with this function call, typically the mouse click when selecting from the calendar grid.
* @param {?=} closeCalendar If the calendar should be closed when a date is selected, used with DatePicker and DateTimePicker.
* @return {?}
*/
function (day, formEvent, event, closeCalendar) {
if (formEvent === void 0) { formEvent = true; }
if (event) {
event.stopPropagation();
}
if (!day.blocked && !day.disabled) {
if (this.calType === 'single') {
this.selectedDay = day;
this.selectedDayChange.emit(this.selectedDay);
this.refreshSelected();
if (this.init) {
this.updateDatePickerInputEmitter();
}
if (formEvent) {
this.onChange({ date: day.date });
}
if (closeCalendar) {
this.closeCalendar.emit();
}
}
else {
if (this.selectCounter === 2) {
this.selectCounter = 0;
}
if (this.selectCounter === 1 && day.date !== this.selectedRangeLast.date) {
this.selectedRangeLast = day;
this.selectedRangeLastChange.emit(this.selectedRangeLast);
this.selectCounter++;
this.refreshSelected();
this.constructCalendar();
if (this.init) {
this.updateDatePickerInputEmitter();
}
if (formEvent) {
this.onChange({ date: this.selectedRangeFirst.date, rangeEnd: day.date });
}
}
if (this.selectCounter === 0) {
this.selectedRangeLast = day;
this.selectedRangeLastChange.emit(this.selectedRangeLast);
this.selectedRangeFirst = day;
this.selectedRangeFirstChange.emit(this.selectedRangeFirst);
this.selectCounter++;
this.refreshSelected();
this.constructCalendar();
if (this.init) {
this.updateDatePickerInputEmitter();
}
if (formEvent) {
this.onChange({ date: day.date, rangeEnd: day.date });
}
}
if (this.selectedRangeFirst.date > this.selectedRangeLast.date) {
/** @type {?} */
var tempSelectedRangeFirst = this.selectedRangeFirst;
this.selectedRangeFirst = this.selectedRangeLast;
this.selectedRangeFirstChange.emit(this.selectedRangeFirst);
this.selectedRangeLast = tempSelectedRangeFirst;
this.selectedRangeLastChange.emit(this.selectedRangeLast);
this.refreshSelected();
this.constructCalendar();
if (this.init) {
this.updateDatePickerInputEmitter();
}
if (formEvent) {
this.onChange({ date: this.selectedRangeFirst.date, rangeEnd: this.selectedRangeLast.date });
}
}
}
}
this.isInvalidDateInput.emit(false);
};
/** @hidden */
/**
* @hidden
* @param {?} month
* @return {?}
*/
CalendarComponent.prototype.setCurrentMonth = /**
* @hidden
* @param {?} month
* @return {?}
*/
function (month) {
// get the current date of the month
/** @type {?} */
var currentDate = this.date.getDate();
// get the number of days in the new month
/** @type {?} */
var daysInNewMonth = new Date(this.date.getFullYear(), month + 1, 0).getDate();
/*
if the currentDate > daysInNewMonth, set the date to the first for now, to prevent skipping a month
in the event that the currentDate is 31 and the next month has 30 days
*/
if (currentDate > daysInNewMonth) {
this.date.setDate(1);
}
// set the month
this.date.setMonth(month);
// if currentDate > daysInNewMonth, restore the date to whichever number is lower, today's date or the number of days in this month
if (currentDate > daysInNewMonth) {
this.date.setDate(Math.min(currentDate, daysInNewMonth));
}
this.month = this.date.getMonth();
this.monthName = this.monthsFullName[this.date.getMonth()];
this.year = this.date.getFullYear();
};
/** @hidden */
/**
* @hidden
* @param {?} selectedMonth
* @param {?=} event
* @return {?}
*/
CalendarComponent.prototype.selectMonth = /**
* @hidden
* @param {?} selectedMonth
* @param {?=} event
* @return {?}
*/
function (selectedMonth, event) {
if (event) {
event.stopPropagation();
}
this.selectedMonth = selectedMonth;
this.setCurrentMonth(selectedMonth);
this.constructCalendar();
this.openDaySelection();
};
/** @hidden */
/**
* @hidden
* @param {?} year
* @return {?}
*/
CalendarComponent.prototype.setCurrentYear = /**
* @hidden
* @param {?} year
* @return {?}
*/
function (year) {
this.date.setFullYear(year);
this.year = this.date.getFullYear();
};
/** @hidden */
/**
* @hidden
* @param {?} selectedYear
* @param {?=} event
* @return {?}
*/
CalendarComponent.prototype.selectYear = /**
* @hidden
* @param {?} selectedYear
* @param {?=} event
* @return {?}
*/
function (selectedYear, event) {
if (event) {
event.stopPropagation();
}
this.selectedMonth = this.month;
this.setCurrentYear(selectedYear);
this.constructCalendar();
this.openDaySelection();
};
/**
* Displays the month selection grid.
*/
/**
* Displays the month selection grid.
* @return {?}
*/
CalendarComponent.prototype.openMonthSelection = /**
* Displays the month selection grid.
* @return {?}
*/
function () {
if (this.showCalendarYears) {
this.showCalendarYears = false;
this.showCalendarMonths = true;
this.showCalendarDates = false;
}
else {
this.showCalendarMonths = !this.showCalendarMonths;
this.showCalendarYears = false;
this.showCalendarDates = !this.showCalendarDates;
}
};
/**
* Displays the year selection grid.
*/
/**
* Displays the year selection grid.
* @return {?}
*/
CalendarComponent.prototype.openYearSelection = /**
* Displays the year selection grid.
* @return {?}
*/
function () {
if (this.showCalendarMonths) {
this.showCalendarMonths = false;
this.showCalendarYears = true;
this.showCalendarDates = false;
}
else {
this.showCalendarYears = !this.showCalendarYears;
this.showCalendarMonths = false;
this.showCalendarDates = !this.showCalendarDates;
}
};
/**
* Displays the date selection grid.
*/
/**
* Displays the date selection grid.
* @return {?}
*/
CalendarComponent.prototype.openDaySelection = /**
* Displays the date selection grid.
* @return {?}
*/
function () {
this.showCalendarMonths = false;
this.showCalendarYears = false;
this.showCalendarDates = true;
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.onEscapeKeydownHandler = /**
* @hidden
* @return {?}
*/
function () {
this.showCalendarDates = true;
this.showCalendarMonths = false;
this.showCalendarYears = false;
};
/** @hidden */
/**
* @hidden
* @param {?} e
* @return {?}
*/
CalendarComponent.prototype.onClickHandler = /**
* @hidden
* @param {?} e
* @return {?}
*/
function (e) {
/** @type {?} */
var target = e.target;
if (!this.eRef.nativeElement.contains(target)) {
this.showCalendarDates = true;
this.showCalendarMonths = false;
this.showCalendarYears = false;
}
};
/** @hidden */
/**
* @hidden
* @param {?} date
* @return {?}
*/
CalendarComponent.prototype.validateDateFromDatePicker = /**
* @hidden
* @param {?} date
* @return {?}
*/
function (date) {
if (!date) {
return true;
}
/** @type {?} */
var month = date.getMonth();
/** @type {?} */
var day = date.getDate();
/** @type {?} */
var year = date.getFullYear();
if (isNaN(month) || isNaN(day) || isNaN(year)) {
return true;
}
if (year < 1000 || year > 3000 || month < 0 || month > 11) {
return true;
}
if (day < 1 || day > this.determineDaysInMonth(month, year)) {
return true;
}
return false;
};
/** @hidden */
/**
* @hidden
* @return {?}
*/
CalendarComponent.prototype.resetSelection = /**
* @hidden
* @return {?}
*/
function () {
if (this.calType === 'single') {
this.selectedDay = { date: null };
this.selectedDayChange.emit(this.selectedDay);
}
else {
this.selectedRangeFirst = { date: null };
this.selectedRangeFirstChange.emit(this.selectedRangeFirst);
this.selectedRangeLast = { date: null };
this.selectedRangeLastChange.emit(this.selectedRangeLast);
}
this.date = new Date();
this.year = this.date.getFullYear();
this.month = this.date.getMonth();
this.monthName = this.monthsFullName[this.date.getMonth()];
this.day = this.date.getDate();
this.selectedMonth = null;
this.firstYearCalendarList = this.year;
this.selectCounter = 0;
this.calendarYearsList = [];
this.constructCalendarYearsList();
this.constructCalendar();
};
/** @hidden */
/**
* @hidden
* @param {?} event
* @param {?} year
* @return {?}
*/
CalendarComponent.prototype.onKeydownYearHandler = /**
* @hidden
* @param {?} event
* @param {?} year
* @return {?}
*/
function (event, year) {
/** @type {?} */
var newFocusedYearId;
if (event.code === 'Space' || event.code === 'Enter') {
event.preventDefault();
this.selectYear(year);
}
else if (event.code === 'ArrowUp') {
event.preventDefault();
if (this.calendarYearsList.indexOf(year) <= 3) {
this.loadPrevYearsList();
this.cd.detectChanges();
}
newFocusedYearId = '#' + this.id + '-fd-year-' + (year - 4);
}
else if (event.code === 'ArrowDown') {
event.preventDefault();
if (this.calendarYearsList.indexOf(year) >= 8) {
this.loadNextYearsList();
this.cd.detectChanges();
}
newFocusedYearId = '#' + this.id + '-fd-year-' + (year + 4);
}
else if (event.code === 'ArrowLeft') {
event.preventDefault();
if (year === this.calendarYearsList[0]) {
this.loadPrevYearsList();
this.cd.detectChanges();
}
newFocusedYearId = '#' + this.id + '-fd-year-' + (year - 1);
}
else if (event.code === 'ArrowRight') {
event.preventDefault();
if (year === this.calendarYearsList[this.calendarYearsList.length - 1]) {
this.loadNextYearsList();
this.cd.detectChanges();
}
newFocusedYearId = '#' + this.id + '-fd-year-' + (year + 1);
}
else if (event.code === 'Tab' && !event.shiftKey) {
if (!this.allowFocusEscape) {
event.preventDefault();
this.focusElement('#arrowLeft');
}
}
if (newFocusedYearId) {
this.focusElement(newFocusedYearId);
}
};
/** @hidden */
/**
* @hidden
* @param {?} event
* @param {?} month
* @return {?}
*/
CalendarComponent.prototype.onKeydownMonthHandler = /**
* @hidden
* @param {?} event
* @param {?} month
* @return {?}
*/
function (event, month) {
/** @type {?} */
var newFocusedMonthId;
if (event.code === 'Space' || event.code === 'Enter') {
event.preventDefault();
this.selectMonth(month);
}
else if (event.code === 'ArrowUp') {
event.preventDefault();
newFocusedMonthId = '#' + this.id + '-fd-month-' + (month - 4);
}
else if (event.code === 'ArrowDown') {
event.preventDefault();
newFocusedMonthId = '#' + this.id + '-fd-month-' + (month + 4);
}
else if (event.code === 'ArrowLeft') {
event.preventDefault();
if (month === 0) {
newFocusedMonthId = '#' + this.id + '-fd-month-11';
}
else {
newFocusedMonthId = '#' + this.id + '-fd-month-' + (month - 1);
}
}
else if (event.code === 'ArrowRight') {
event.preventDefault();
if (month === 11) {
newFocusedMonthId = '#' + this.id + '-fd-month-0';
}
else {
newFocusedMonthId = '#' + this.id + '-fd-month-' + (month + 1);
}
}
else if (event.code === 'Tab' && !event.shiftKey) {
if (!this.allowFocusEscape) {
event.preventDefault();
this.focusElement('#arrowLeft');
}
}
if (newFocusedMonthId) {
this.focusElement(newFocusedMonthId);
}
};
/** @hidden */
/**
* @hidden
* @param {?} event
* @param {?} cell
* @return {?}
*/
CalendarComponent.prototype.onKeydownDayHandler = /**
* @hidden
* @param {?} event
* @param {?} cell
* @return {?}
*/
function (event, cell) {
if (event.code === 'Tab' && !event.shiftKey) {
if (!this.allowFocusEscape) {
event.preventDefault();
this.focusElement('#arrowLeft');
}
}
else {
// if the grid has 6 rows, the last cell id is 66, if it has 5 rows it's 56
/** @type {?} */
var lastDay = this.calendarGrid.length === 6 ? 66 : 56;
/** @type {?} */
var currentId = parseInt(event.currentTarget.id.split('-').pop(), 10);
if (event.code === 'Space' || event.code === 'Enter') {
event.preventDefault();
/** @type {?} */
var closeCalendarPopover = true;
this.selectDate(cell, true, null, closeCalendarPopover);
this.newFocusedDayId = '#' + this.id + '-fd-day-' + currentId;
}
else if (event.code === 'ArrowUp') {
event.preventDefault();
if (currentId >= 10 && currentId <= 16) {
// if first row, go to previous month
this.goToPreviousMonth();
/** @type {?} */
var lastDigit = currentId.toString().split('').pop();
this.newFocusedDayId = '#' + this.id + '-fd-day-' + this.calendarGrid.length.toString() + lastDigit;
}
else {
this.newFocusedDayId = '#' + this.id + '-fd-day-' + (currentId - 10);
}
}
else if (event.code === 'ArrowDown') {
event.preventDefault();
if (currentId >= lastDay - 6 && currentId <= lastDay) {
// if last row, go to next month
this.goToNextMonth();
/** @type {?} */
var lastDigit = currentId.toString().split('').pop();
this.newFocusedDayId = '#' + this.id + '-fd-day-1' + lastDigit;
}
else {
this.newFocusedDayId = '#' + this.id + '-fd-day-' + (currentId + 10);
}
}
else if (event.code === 'ArrowLeft') {
event.preventDefault();
if (currentId === 10) {
// if the first day is selected, go to the last day of the previous month
this.goToPreviousMonth();
lastDay = this.calendarGrid.length === 6 ? 66 : 56;
this.newFocusedDayId = '#' + this.id + '-fd-day-' + lastDay;
}
else if (currentId.toString().split('').pop() === '0') {
// if the last digit is 0, skip to the last day of the previous week
this.newFocusedDayId = '#' + this.id + '-fd-day-' + (currentId - 4);
}
else {
this.newFocusedDayId = '#' + this.id + '-fd-day-' + (currentId - 1);
}
}
else if (event.code === 'ArrowRight') {
event.preventDefault();
if (currentId === lastDay) {
// if the last day is selected, go to the first day of the next month
this.goToNextMonth();
this.newFocusedDayId = '#' + this.id + '-fd-day-10';
}
else if (currentId.toString().split('').pop() === '6') {
// else if the last digit is 6, skip to the first day of the next week
this.newFocusedDayId = '#' + this.id + '-fd-day-' + (currentId + 4);
}
else {
this.newFocusedDayId = '#' + this.id + '-fd-day-' + (currentId + 1);
}
}
if (this.newFocusedDayId) {
this.focusElement(this.newFocusedDayId);
}
}
};
/** @hidden */
/**
* @hidden
* @param {?} elementSelector
* @return {?}
*/
CalendarComponent.prototype.focusElement = /**
* @hidden
* @param {?} elementSelector
* @return {?}
*/
function (elementSelector) {
/** @type {?} */
var elementToFocus = this.eRef.nativeElement.querySelector(elementSelector);
if (elementToFocus) {
elementToFocus.focus();
}
};
/** @hidden */
/**
* @hidden
* @param {?} date
* @return {?}
*/
CalendarComponent.prototype.updateFromDatePicker = /**
* @hidden
* @param {?} date
* @return {?}
*/
function (date) {
if (this.calType === 'single') {
/** @type {?} */
var singleDate = this.dateAdapter.parse(date);
this.invalidDate = this.validateDateFromDatePicker(singleDate);
if (!this.invalidDate) {
this.selectedDay.date = new Date(singleDate.getFullYear(), singleDate.getMonth(), singleDate.getDate());
this.date = new Date(singleDate.getFullYear(), singleDate.getMonth(), singleDate.getDate());
this.year = this.date.getFullYear();
this.month = this.date.getMonth();
this.monthName = this.monthsFullName[this.date.getMonth()];
this.isInvalidDateInput.emit(this.invalidDate);
this.constructCalendar();
this.constructCalendarYearsList();
this.updateDatePickerInputEmitter();
}
else {
this.isInvalidDateInput.emit(this.invalidDate);
this.resetSelection();
}
}
else {
/** @type {?} */
var currentDates = date.split(this.dateAdapter.rangeDelimiter);