import { Component, ElementRef, ViewEncapsulation, ViewChild, Renderer2, ChangeDetectorRef, HostBinding } from '@angular/core'; import { IMyDate, IMyDateRange, IMyMonth, IMyCalendarDay, IMyCalendarMonth, IMyCalendarYear, IMyWeek, IMyOptions, IMySelectorPosition, IMyCalendarViewChanged, IMyRangeDateSelection, IMyDateModel, IMyMonthRow } from '../../interfaces/public-api'; import { UtilService } from '../../services/public-api'; import { DefaultView, KeyCode, MonthId, ResetDateType } from '../../enums/public-api'; import { DOT, UNDER_LINE, D, M, Y, DATE_ROW_COUNT, DATE_COL_COUNT, MONTH_ROW_COUNT, MONTH_COL_COUNT, YEAR_ROW_COUNT, YEAR_COL_COUNT, SU, MO, TU, WE, TH, FR, SA, EMPTY_STR, STYLE } from '../../constants/constants'; import { TimePickerPanelComponent } from '@farris/ui-time-picker'; import { flatten, cloneDeep } from 'lodash-es'; @Component({ selector: 'farris-datepicker-calendar', templateUrl: './calendar.component.html', providers: [UtilService], encapsulation: ViewEncapsulation.None }) export class CalendarComponent { @ViewChild('selectorEl') selectorEl: ElementRef; @ViewChild('styleEl') styleEl: ElementRef; @ViewChild('endTimeRef') endTimeRef: TimePickerPanelComponent; @HostBinding('style.position') position = 'static'; opts: IMyOptions; visibleMonth: IMyMonth = { monthTxt: EMPTY_STR, monthNbr: 0, year: 0, yearTxt: EMPTY_STR }; visibleMonth_range: IMyMonth = { monthTxt: EMPTY_STR, monthNbr: 0, year: 0, yearTxt: EMPTY_STR }; selectedMonth: IMyMonth = { monthNbr: 0, year: 0 }; selectedMonth_range: IMyMonth = { monthNbr: 0, year: 0 }; selectedDate: IMyDate = { year: 0, month: 0, day: 0 }; selectedDateRange: IMyDateRange = { begin: { year: 0, month: 0, day: 0 }, end: { year: 0, month: 0, day: 0 } }; selectedWeek: IMyWeek = { weekNbr: 0, year: 0 }; weekDays: Array = []; dates: Array = []; dates_range: Array = []; months: Array = []; months_range: Array = []; years: Array> = []; years_range: Array> = []; timeVlaue: string; timeVlaue_range: string; dayIdx = 0; weekDayOpts: Array = [SU, MO, TU, WE, TH, FR, SA]; selectMonth = false; selectMonth_range = false; selectYear = false; selectYear_range = false; selectTime = false; dateChanged: (dm: IMyDateModel, close: boolean) => void; calendarViewChanged: (cvc: IMyCalendarViewChanged) => void; rangeDateSelection: (rds: IMyRangeDateSelection) => void; closedByEsc: () => void; selectorPos: IMySelectorPosition = null; scrollDiff = 0; prevViewDisabled = false; nextViewDisabled = false; prevDobViewDisabled = false; nextDobViewDisabled = false; prevViewDisabled_range = false; nextViewDisabled_range = false; prevDobViewDisabled_range = false; nextDobViewDisabled_range = false; getTimeStr(date: Date): string { const hour = this.utilService.preZero(date.getHours()); const minute = this.utilService.preZero(date.getMinutes()); const second = this.utilService.preZero(date.getSeconds()); return `${hour}:${minute}:${second}`; } // 禁用日期时间控件中的时间段的小时 disabledHours = () => { const min = this.opts.disableUntil; const max = this.opts.disableSince; const currentDate = this.opts.dateRange ? this.selectedDateRange.begin : this.selectedDate; const res = this.utilService.disabledHours(min, max, currentDate); return res; } // 禁用日期时间控件中的时间段的分钟 disabledMinutes = (hour: number) => { const min = this.opts.disableUntil; const max = this.opts.disableSince; const currentDate = this.opts.dateRange ? this.selectedDateRange.begin : this.selectedDate; const res = this.utilService.disabledMinutes(min, max, hour, currentDate); return res; } // 禁用日期时间控件中的时间段的秒 disabledSeconds = (hour: number, minute: number) => { const min = this.opts.disableUntil; const max = this.opts.disableSince; const currentDate = this.opts.dateRange ? this.selectedDateRange.begin : this.selectedDate; const res = this.utilService.disabledSeconds(min, max, hour, minute, currentDate); return res; } constructor(private renderer: Renderer2, private cdr: ChangeDetectorRef, private utilService: UtilService) { } initialize( opts: IMyOptions, defaultMonth: string, selectorPos: IMySelectorPosition, inputValue: string, dc: (dm: IMyDateModel, close: boolean) => void, cvc: (cvc: IMyCalendarViewChanged) => void, rds: (rds: IMyRangeDateSelection) => void, cbe: () => void ): void { this.opts = opts; this.selectorPos = selectorPos; this.weekDays.length = 0; const { defaultView, dateRange, firstDayOfWeek, dayLabels, stylesData, yearTxt } = this.opts; this.visibleMonth.yearTxt = yearTxt; this.visibleMonth_range.yearTxt = yearTxt; // if (stylesData.styles.length) { // const styleElTemp: any = this.renderer.createElement(STYLE); // this.renderer.appendChild(styleElTemp, this.renderer.createText(stylesData.styles)); // this.renderer.appendChild(this.styleEl.nativeElement, styleElTemp); // } this.dayIdx = this.weekDayOpts.indexOf(firstDayOfWeek); if (this.dayIdx !== -1) { let idx: number = this.dayIdx; // tslint:disable-next-line:prefer-for-of for (let i = 0; i < this.weekDayOpts.length; i++) { this.weekDays.push(dayLabels[this.weekDayOpts[idx]]); idx = this.weekDayOpts[idx] === SA ? 0 : idx + 1; } } let today: IMyDate = this.getToday(); const isInDisableRange = this.utilService.isDisabledDate(today, this.opts); today = !isInDisableRange ? today : this.utilService.getNearDate(today, this.opts.disableUntil, this.opts.disableSince); switch (defaultView) { case DefaultView.Month: this.selectedMonth = { monthNbr: 0, year: today.year }; this.selectedMonth_range = { monthNbr: 0, year: today.year + 1 }; break; case DefaultView.Year: this.selectedMonth = { monthNbr: 0, year: today.year }; this.selectedMonth_range = { monthNbr: 0, year: today.year + 10 }; break; default: this.selectedMonth = { monthNbr: today.month, year: today.year }; if (today.month >= 12) { this.selectedMonth_range = { monthNbr: 1, year: today.year + 1 }; } else { this.selectedMonth_range = { monthNbr: today.month + this.opts.monthRangeValue, year: today.year }; } break; } if (defaultMonth && defaultMonth.length) { this.selectedMonth = this.utilService.parseDefaultMonth(defaultMonth); this.selectedMonth_range = this.utilService.parseDefaultMonth(defaultMonth); if (this.selectedMonth_range.monthNbr >= 12) { this.selectedMonth_range.year++; this.selectedMonth_range.monthNbr = 1; } else { this.selectedMonth_range.monthNbr = this.selectedMonth_range.monthNbr + this.opts.monthRangeValue; } } if (!dateRange) { // Single date mode const date: IMyDate = this.utilService.isDateValid(inputValue, this.opts, true); if (this.utilService.isInitializedDate(date)) { this.selectedDate = date; const hour = this.utilService.preZero(date.hour); const minute = this.utilService.preZero(date.minute); const second = this.utilService.preZero(date.second); this.timeVlaue = `${hour}:${minute}:${second}`; this.selectedMonth = { monthNbr: date.month, year: date.year }; } } else { // Date range mode const { begin, end } = this.utilService.isDateValidDateRange(inputValue, this.opts); if (this.utilService.isInitializedDate(begin) && this.utilService.isInitializedDate(end)) { this.selectedDateRange = { begin, end }; const hour = this.utilService.preZero(begin.hour); const minute = this.utilService.preZero(begin.minute); const second = this.utilService.preZero(begin.second); this.timeVlaue = `${hour}:${minute}:${second}`; const _hour = this.utilService.preZero(end.hour); const _minute = this.utilService.preZero(end.minute); const _second = this.utilService.preZero(end.second); this.timeVlaue_range = `${_hour}:${_minute}:${_second}`; this.selectedMonth = { monthNbr: begin.month, year: begin.year }; if (begin.month === end.month && begin.year === end.year) { if (end.month >= 12) { this.selectedMonth_range = { monthNbr: 1, year: end.year + 1 }; } else { let endyear = end.year; if (defaultView === DefaultView.Month) { endyear = endyear + 1; } this.selectedMonth_range = { monthNbr: end.month + this.opts.monthRangeValue, year: endyear }; } } else { if (defaultView === DefaultView.Month && begin.year === end.year) { this.selectedMonth_range = { monthNbr: end.month, year: end.year + 1 }; } else { this.selectedMonth_range = { monthNbr: end.month, year: end.year }; } } const weekNbr = this.utilService.getWeekNumber(begin) === this.utilService.getWeekNumber(end) ? this.utilService.getWeekNumber(begin) : 0; this.selectedWeek = { weekNbr, year: begin.year }; } } this.dateChanged = dc; this.calendarViewChanged = cvc; this.rangeDateSelection = rds; this.closedByEsc = cbe; this.setCalendarVisibleMonth(); if (defaultView === DefaultView.Month) { this.onMonthViewBtnClicked(); if (dateRange) { this.onMonthViewBtnClicked(true); } } else if (defaultView === DefaultView.Year) { this.onYearViewBtnClicked(); if (dateRange) { this.onYearViewBtnClicked(true); } } } resetDateValue(value: ResetDateType): void { if (value === ResetDateType.singleDate || value === ResetDateType.both) { this.selectedDate = this.utilService.resetDate(); } if (value === ResetDateType.dateRange || value === ResetDateType.both) { this.selectedDateRange.begin = this.utilService.resetDate(); this.selectedDateRange.end = this.utilService.resetDate(); } } resetMonthYearSelect(isSecondCalendar?: boolean): void { if (!isSecondCalendar) { this.selectMonth = false; this.selectYear = false; } else { this.selectMonth_range = false; this.selectYear_range = false; } } onMonthViewBtnClicked(isSecondCalendar?: boolean): void { this.selectTime = false; if (!isSecondCalendar) { this.selectMonth = !this.selectMonth; this.selectYear = false; if (this.selectMonth) { this.generateMonths(isSecondCalendar); } else { this.visibleMonth.year = this.selectedMonth.year; } } else { this.selectMonth_range = !this.selectMonth_range; this.selectYear_range = false; if (this.selectMonth_range) { this.generateMonths(isSecondCalendar); } else { this.visibleMonth_range.year = this.selectedMonth_range.year; } this.cdr.detectChanges(); } } onMonthCellClicked(cell: IMyCalendarMonth, isSecondCalendar: boolean): void { if (!isSecondCalendar) { const { year, monthNbr } = this.visibleMonth; const mc: boolean = cell.nbr !== monthNbr; this.visibleMonth = { monthTxt: this.opts.monthLabels[cell.nbr], monthNbr: cell.nbr, year, yearTxt: this.opts.yearTxt }; this.selectedMonth.year = this.visibleMonth.year; if (this.opts.showType === 2) { this.toSelectMonth(this.visibleMonth); } else { this.generateCalendar(cell.nbr, year, mc, isSecondCalendar); this.selectMonth = false; } } else { const { year, monthNbr } = this.visibleMonth_range; const mc: boolean = cell.nbr !== monthNbr; this.visibleMonth_range = { monthTxt: this.opts.monthLabels[cell.nbr], monthNbr: cell.nbr, year, yearTxt: this.opts.yearTxt }; this.selectedMonth_range.year = this.visibleMonth_range.year; if (this.opts.showType === 2) { this.toSelectMonth(this.visibleMonth_range); } else { this.generateCalendar(cell.nbr, year, mc, isSecondCalendar); this.selectMonth_range = false; } } } onMonthCellKeyDown(cell: IMyCalendarMonth) { // Make possible to move focus by arrow keys const { sourceRow, sourceCol } = this.getSourceRowAndColumnFromEvent(event); const { moveFocus, targetRow, targetCol } = this.getTargetFocusRowAndColumn( event, sourceRow, sourceCol, MONTH_ROW_COUNT, MONTH_COL_COUNT ); if (moveFocus) { this.focusCellElement(M, targetRow, targetCol); } } onYearViewBtnClicked(isSecondCalendar?: boolean): void { this.selectTime = false; if (!isSecondCalendar) { this.visibleMonth.year = this.selectedMonth.year; if (!this.selectYear) { this.generateYears(this.visibleMonth.year, isSecondCalendar); } else { this.generateCalendar(this.visibleMonth.monthNbr, this.visibleMonth.year, false, isSecondCalendar); } this.selectYear = this.opts.showType === 3 ? true : !this.selectYear; if (this.opts.showType === 2) { this.selectMonth = !this.selectMonth; } else { this.selectMonth = false; } // this.selectYear = !this.selectYear; // this.selectMonth = false; } else { this.visibleMonth_range.year = this.selectedMonth_range.year; if (!this.selectYear_range) { this.generateYears(this.visibleMonth_range.year, isSecondCalendar); } else { this.generateCalendar(this.visibleMonth_range.monthNbr, this.visibleMonth_range.year, false, isSecondCalendar); } this.selectYear_range = this.opts.showType === 3 ? true : !this.selectYear_range; if (this.opts.showType === 2) { this.selectMonth_range = !this.selectMonth_range; } else { this.selectMonth_range = false; } } this.cdr.detectChanges(); } onYearCellClicked(cell: IMyCalendarYear, isSecondCalendar?: boolean): void { if (!isSecondCalendar) { const { year, monthNbr, monthTxt } = this.visibleMonth; const yc: boolean = cell.year !== year; this.visibleMonth = { monthTxt, monthNbr, year: cell.year, yearTxt: this.opts.yearTxt }; this.selectedMonth.year = this.visibleMonth.year; if (this.opts.showType === 3) { this.toSelectYear({ year: this.visibleMonth.year }); } else if (this.opts.showType === 2) { this.generateMonths(isSecondCalendar); this.selectYear = false; this.selectMonth = true; } else { this.generateCalendar(monthNbr, cell.year, yc, isSecondCalendar); this.selectYear = false; } } else { const { year, monthNbr, monthTxt } = this.visibleMonth_range; const yc: boolean = cell.year !== year; this.visibleMonth_range = { monthTxt, monthNbr, year: cell.year, yearTxt: this.opts.yearTxt }; this.selectedMonth_range.year = this.visibleMonth_range.year; if (this.opts.showType === 3) { this.toSelectYear({ year: this.visibleMonth_range.year }); } else if (this.opts.showType === 2) { this.generateMonths(isSecondCalendar); this.selectYear_range = false; this.selectMonth_range = true; } else { this.generateCalendar(monthNbr, cell.year, yc, isSecondCalendar); this.selectYear_range = false; } } } onYearCellKeyDown(cell: IMyCalendarYear) { // Make possible to move focus by arrow keys const { sourceRow, sourceCol } = this.getSourceRowAndColumnFromEvent(event); const { moveFocus, targetRow, targetCol } = this.getTargetFocusRowAndColumn( event, sourceRow, sourceCol, YEAR_ROW_COUNT, YEAR_COL_COUNT ); if (moveFocus) { this.focusCellElement(Y, targetRow, targetCol); } } generateMonths(isSecondCalendar?: boolean): void { const today: IMyDate = this.getToday(); const { disableUntil, disableSince } = this.opts; // tslint:disable-next-line:one-variable-per-declaration let year: number, monthNbr: number; if (!isSecondCalendar) { this.months.length = 0; year = this.visibleMonth.year; monthNbr = this.visibleMonth.monthNbr; } else { this.months_range.length = 0; year = this.visibleMonth_range.year; monthNbr = this.visibleMonth_range.monthNbr; } for (let i = 1; i <= 12; i += 3) { const row: Array = []; for (let j = i; j < i + 3; j++) { const disabled: boolean = this.utilService.isMonthDisabledByDisableUntil( { year, month: j, day: this.daysInMonth(j, year) }, disableUntil ) || this.utilService.isMonthDisabledByDisableSince({ year, month: j, day: 1 }, disableSince); row.push({ nbr: j, name: this.opts.monthLabels[j], currMonth: j === today.month && year === today.year, disabled, monthObj: { year, month: j } }); } if (!isSecondCalendar) { this.months.push({ row, year }); } else { this.months_range.push({ row, year }); } } this.setMonthViewHeaderBtnDisabledState(year, isSecondCalendar); } generateYears(inputYear: number, isSecondCalendar?: boolean): void { const { minYear, maxYear, disableUntil, disableSince } = this.opts; let y: number = inputYear - (inputYear % 10); const { year, monthNbr } = this.visibleMonth; if (!isSecondCalendar) { this.years.length = 0; } else { this.years_range.length = 0; const allYears = flatten(this.years_range); if (allYears.findIndex(n => n.year == inputYear) > -1) { y = this.years_range[3][2].year; } } const today: IMyDate = this.getToday(); for (let i = y - 1; i < y + 10; i += 3) { const row: Array = []; for (let j = i; j < i + 3; j++) { const disabled: boolean = this.utilService.isMonthDisabledByDisableUntil( { year: j, month: monthNbr, day: this.daysInMonth(monthNbr, j) }, disableUntil ) || this.utilService.isMonthDisabledByDisableSince({ year: j, month: monthNbr, day: 1 }, disableSince); const minMax: boolean = j < minYear || j > maxYear; row.push({ year: j, currYear: j === today.year, selected: j === year, disabled: disabled || minMax, yearObj: { year: j } }); } if (!isSecondCalendar) { this.years.push(row); } else { this.years_range.push(row); } } if (!isSecondCalendar) { this.setYearViewHeaderBtnDisabledState(this.years[0][1].year, this.years[3][1].year, isSecondCalendar); } else { this.setYearViewHeaderBtnDisabledState( this.years_range[0][1].year, this.years_range[3][1].year, isSecondCalendar ); } } setCalendarVisibleMonth(): void { // Sets visible month of calendar const { year, monthNbr } = this.selectedMonth; this.visibleMonth = { monthTxt: this.opts.monthLabels[monthNbr], monthNbr, year, yearTxt: this.opts.yearTxt }; // Create current month if (this.opts.dateRange) { this.visibleMonth_range = { monthTxt: this.opts.monthLabels[this.selectedMonth_range.monthNbr], monthNbr: this.selectedMonth_range.monthNbr, year: this.selectedMonth_range.year, yearTxt: this.opts.yearTxt }; this.generateCalendar(this.selectedMonth_range.monthNbr, this.selectedMonth_range.year, true, true); } this.generateCalendar(monthNbr, year, true, false); } onPrevNavigateBtnClicked(event?: any, isSecondCalendar?: boolean): void { if (!isSecondCalendar) { if (event) { if (!this.selectMonth && !this.selectYear) { this.setDateViewMonth(isSecondCalendar, false); } else if (this.selectMonth) { this.visibleMonth.year--; this.generateMonths(isSecondCalendar); } else if (this.selectYear) { this.generateYears(this.years[2][2].year - 10); } } else { if (!this.selectMonth && !this.selectYear) { this.visibleMonth.year--; this.setDateViewMonth(isSecondCalendar); } else if (this.selectMonth) { this.visibleMonth.year--; this.generateMonths(isSecondCalendar); } else if (this.selectYear) { this.generateYears(this.years[2][2].year - 10, isSecondCalendar); } } } else { if (event) { if (!this.selectMonth_range && !this.selectYear_range) { this.setDateViewMonth(isSecondCalendar, false); } else if (this.selectMonth_range) { this.visibleMonth_range.year--; this.generateMonths(isSecondCalendar); } else if (this.selectYear_range) { this.generateYears(this.years_range[2][2].year - 10); } } else { if (!this.selectMonth_range && !this.selectYear_range) { this.visibleMonth_range.year--; this.setDateViewMonth(isSecondCalendar); } else if (this.selectMonth_range) { this.visibleMonth_range.year--; this.generateMonths(isSecondCalendar); } else if (this.selectYear_range) { this.generateYears(this.years_range[2][2].year - 10, isSecondCalendar); } } } } onNextNavigateBtnClicked(event?: any, isSecondCalendar?: boolean): void { if (!isSecondCalendar) { if (event) { if (!this.selectMonth && !this.selectYear) { this.setDateViewMonth(isSecondCalendar, true); } else if (this.selectMonth) { this.visibleMonth.year++; this.generateMonths(); } else if (this.selectYear) { this.generateYears(this.years[2][2].year + 10); } } else { if (!this.selectMonth && !this.selectYear) { this.visibleMonth.year++; this.setDateViewMonth(isSecondCalendar); } else if (this.selectMonth) { this.visibleMonth.year++; this.generateMonths(); } else if (this.selectYear) { this.generateYears(this.years[2][2].year + 10); } } } else { if (event) { if (!this.selectMonth_range && !this.selectYear_range) { this.setDateViewMonth(isSecondCalendar, true); } else if (this.selectMonth_range) { this.visibleMonth_range.year++; this.generateMonths(isSecondCalendar); } else if (this.selectYear_range) { this.generateYears(this.years_range[2][2].year + 10, isSecondCalendar); } } else { if (!this.selectMonth_range && !this.selectYear_range) { this.visibleMonth_range.year++; this.setDateViewMonth(isSecondCalendar); } else if (this.selectMonth_range) { this.visibleMonth_range.year++; this.generateMonths(isSecondCalendar); } else if (this.selectYear_range) { this.generateYears(this.years_range[2][2].year + 10, isSecondCalendar); } } } } setDateViewMonth(isSecondCalendar?: boolean, isNext?: boolean): void { let change: number; if (isNext === undefined) { change = 0; } else { change = isNext ? 1 : -1; } if (!isSecondCalendar) { const { year, monthNbr } = this.visibleMonth; const d: Date = this.getDate(year, monthNbr, 1); d.setMonth(d.getMonth() + change); const y: number = d.getFullYear(); const m: number = d.getMonth() + 1; this.visibleMonth = { monthTxt: this.opts.monthLabels[m], monthNbr: m, year: y, yearTxt: this.opts.yearTxt }; this.generateCalendar(m, y, true, isSecondCalendar); } else { const { year, monthNbr } = this.visibleMonth_range; const d: Date = this.getDate(year, monthNbr, 1); d.setMonth(d.getMonth() + change); const y: number = d.getFullYear(); const m: number = d.getMonth() + 1; this.visibleMonth_range = { monthTxt: this.opts.monthLabels[m], monthNbr: m, year: y, yearTxt: this.opts.yearTxt }; this.generateCalendar(m, y, true, isSecondCalendar); } } onCloseSelector(event: any): void { const keyCode: number = this.utilService.getKeyCodeFromEvent(event); if (keyCode === KeyCode.esc) { this.closedByEsc(); } } onDayCellClicked(cell: IMyCalendarDay, isSecondCalendar?: boolean): void { if (cell.cmo === 1) { this.onPrevNavigateBtnClicked(true, isSecondCalendar); } else if (cell.cmo === 3) { this.onNextNavigateBtnClicked(true, isSecondCalendar); } this.selectDate(cell.dateObj); this.resetMonthYearSelect(isSecondCalendar); } onDayCellKeyDown(cell: IMyCalendarDay) { // Make possible to move focus by arrow keys const { sourceRow, sourceCol } = this.getSourceRowAndColumnFromEvent(event); const { moveFocus, targetRow, targetCol } = this.getTargetFocusRowAndColumn( event, sourceRow, sourceCol, DATE_ROW_COUNT, DATE_COL_COUNT ); if (moveFocus) { this.focusCellElement(D, targetRow, targetCol); } } onDayCellMouseEnter(cell: any, isSecondCalendar?: boolean) { if (isSecondCalendar) { for (const w of this.dates) { for (const day of w.week) { day.range = (this.utilService.isDateSameOrEarlier(this.selectedDateRange.begin, day.dateObj) && this.utilService.isDateSameOrEarlier(day.dateObj, cell.dateObj)) || (this.utilService.isDateSameOrEarlier(day.dateObj, this.selectedDateRange.begin) && this.utilService.isDateSameOrEarlier(cell.dateObj, day.dateObj)); } } } else { for (const w of this.dates_range) { for (const day of w.week) { day.range = (this.utilService.isDateSameOrEarlier(this.selectedDateRange.begin, day.dateObj) && this.utilService.isDateSameOrEarlier(day.dateObj, cell.dateObj)) || (this.utilService.isDateSameOrEarlier(day.dateObj, this.selectedDateRange.begin) && this.utilService.isDateSameOrEarlier(cell.dateObj, day.dateObj)); } } } } onDayCellMouseLeave(isSecondCalendar?: boolean) { if (isSecondCalendar) { for (const w of this.dates) { for (const day of w.week) { day.range = false; } } } else { for (const w of this.dates_range) { for (const day of w.week) { day.range = false; } } } } onMonthCellMouseEnter(cell: any, isSecondCalendar?: boolean) { if (isSecondCalendar) { for (const item of this.months) { for (const month of item.row) { month.range = (this.utilService.isDateSameOrEarlier(this.selectedDateRange.begin, month.monthObj) && this.utilService.isDateSameOrEarlier(month.monthObj, cell.monthObj)) || (this.utilService.isDateSameOrEarlier(month.monthObj, this.selectedDateRange.begin) && this.utilService.isDateSameOrEarlier(cell.monthObj, month.monthObj)); } } } else { for (const item of this.months_range) { for (const month of item.row) { month.range = (this.utilService.isDateSameOrEarlier(this.selectedDateRange.begin, month.monthObj) && this.utilService.isDateSameOrEarlier(month.monthObj, cell.monthObj)) || (this.utilService.isDateSameOrEarlier(month.monthObj, this.selectedDateRange.begin) && this.utilService.isDateSameOrEarlier(cell.monthObj, month.monthObj)); } } } } onMonthCellMouseLeave(isSecondCalendar?: boolean) { if (isSecondCalendar) { for (const item of this.months) { for (const month of item.row) { month.range = false; } } } else { for (const item of this.months) { for (const month of item.row) { month.range = false; } } } } onYearCellMouseEnter(cell: any, isSecondCalendar?: boolean) { if (isSecondCalendar) { for (const item of this.years) { for (const year of item) { year.range = (this.utilService.isDateSameOrEarlier(this.selectedDateRange.begin, year.yearObj) && this.utilService.isDateSameOrEarlier(year.yearObj, cell.yearObj)) || (this.utilService.isDateSameOrEarlier(year.yearObj, this.selectedDateRange.begin) && this.utilService.isDateSameOrEarlier(cell.yearObj, year.yearObj)); } } } else { for (const item of this.years_range) { for (const year of item) { year.range = (this.utilService.isDateSameOrEarlier(this.selectedDateRange.begin, year.yearObj) && this.utilService.isDateSameOrEarlier(year.yearObj, cell.yearObj)) || (this.utilService.isDateSameOrEarlier(year.yearObj, this.selectedDateRange.begin) && this.utilService.isDateSameOrEarlier(cell.yearObj, year.yearObj)); } } } } onYearCellMouseLeave(isSecondCalendar?: boolean) { if (isSecondCalendar) { for (const item of this.years) { for (const year of item) { year.range = false; } } } else { for (const item of this.years_range) { for (const year of item) { year.range = false; } } } } onWeekClicked(weekData: IMyWeek) { const showTime = this.opts.returnFormat && this.opts.returnFormat.toLocaleLowerCase().indexOf('hh:mm') > -1; this.selectedWeek = { weekNbr: weekData.weekNbr, year: weekData.year }; if (showTime) { weekData.week[0].dateObj.hour = 0; weekData.week[0].dateObj.minute = 0; weekData.week[0].dateObj.second = 0; weekData.week[6].dateObj.hour = 23; weekData.week[6].dateObj.minute = 59; weekData.week[6].dateObj.second = 59; } this.selectDate(weekData.week[0].dateObj); this.selectDate(weekData.week[6].dateObj); } getSourceRowAndColumnFromEvent(event: any): any { let sourceRow = 0; let sourceCol = 0; if (event.target && event.target.id) { // value of id is for example: m_0_1 (first number = row, second number = column) const arr: Array = event.target.id.split(UNDER_LINE); sourceRow = Number(arr[1]); sourceCol = Number(arr[2]); } return { sourceRow, sourceCol }; } getTargetFocusRowAndColumn(event: any, row: number, col: number, rowCount: number, colCount: number): any { let moveFocus = false; let targetRow: number = row; let targetCol: number = col; const keyCode: number = this.utilService.getKeyCodeFromEvent(event); if (keyCode === KeyCode.upArrow && row > 0) { moveFocus = true; targetRow--; } else if (keyCode === KeyCode.downArrow && row < rowCount) { moveFocus = true; targetRow++; } else if (keyCode === KeyCode.leftArrow && col > 0) { moveFocus = true; targetCol--; } else if (keyCode === KeyCode.rightArrow && col < colCount) { moveFocus = true; targetCol++; } return { moveFocus, targetRow, targetCol }; } focusCellElement(type: string, row: number, col: number): void { const elem: any = this.selectorEl.nativeElement.querySelector(DOT + type + UNDER_LINE + row + UNDER_LINE + col); if (elem) { elem.focus(); } } selectDate(date: IMyDate): void { const { dateFormat, monthLabels, dateRangeDatesDelimiter, closeSelectorOnDateSelect, showTime, returnFormat } = this.opts; if (this.opts.dateRange) { // Date range const isBeginDateInitialized: boolean = this.utilService.isInitializedDate(this.selectedDateRange.begin); const isEndDateInitialized: boolean = this.utilService.isInitializedDate(this.selectedDateRange.end) && JSON.stringify(this.selectedDateRange.begin) !== JSON.stringify(this.selectedDateRange.end); if (isBeginDateInitialized && isEndDateInitialized) { // both already selected - set begin date and reset end date this.selectedDateRange.begin = date; this.selectedDateRange.end = this.utilService.resetDate(); this.rangeDateSelection({ isBegin: true, date, jsDate: this.utilService.getDate(date), dateFormat, formatted: this.utilService.formatDate(date, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(date) }); } else if (!isBeginDateInitialized) { // begin date this.selectedDateRange.begin = date; if (!isEndDateInitialized) { this.selectedDateRange.end = date; } this.rangeDateSelection({ isBegin: true, date, jsDate: this.utilService.getDate(date), dateFormat, formatted: this.utilService.formatDate(date, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(date) }); } else { // second selection const firstDateEarlier: boolean = this.utilService.isDateEarlier(date, this.selectedDateRange.begin); if (firstDateEarlier) { const _date = this.selectedDateRange.begin; this.selectedDateRange.end = _date; this.rangeDateSelection({ isBegin: false, date: _date, jsDate: this.utilService.getDate(_date), dateFormat, formatted: this.utilService.formatDate(_date, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(_date) }); this.selectedDateRange.begin = date; this.rangeDateSelection({ isBegin: true, date, jsDate: this.utilService.getDate(date), dateFormat, formatted: this.utilService.formatDate(date, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(date) }); } else { this.selectedDateRange.end = date; this.rangeDateSelection({ isBegin: false, date, jsDate: this.utilService.getDate(date), dateFormat, formatted: this.utilService.formatDate(date, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(date) }); } if (!this.opts.showTime) { this.dateChanged( this.utilService.getDateModel( null, this.selectedDateRange, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ), closeSelectorOnDateSelect ); } } } else { // Single date this.selectedDate = date; if (!this.opts.showTime) { this.dateChanged( this.utilService.getDateModel( this.selectedDate, null, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ), showTime ? false : closeSelectorOnDateSelect ); } } } toSelectMonth(month: IMyMonth): void { const { dateFormat, monthLabels, dateRangeDatesDelimiter, closeSelectorOnDateSelect, showTime, returnFormat } = this.opts; if (this.opts.dateRange) { // month range const isBeginMonthInitialized: boolean = this.utilService.isInitializedMonth(this.selectedDateRange.begin); const isEndMonthInitialized: boolean = this.utilService.isInitializedMonth(this.selectedDateRange.end); if (isBeginMonthInitialized && isEndMonthInitialized) { // both already selected - set begin date and reset end date this.selectedDateRange.begin = { year: month.year, month: month.monthNbr }; this.selectedDateRange.end = this.utilService.resetDate(); this.rangeDateSelection({ isBegin: true, date: this.selectedDateRange.begin, jsDate: this.utilService.getDate(this.selectedDateRange.begin), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.begin, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.begin) }); } else if (!isBeginMonthInitialized) { // begin date this.selectedDateRange.begin = { year: month.year, month: month.monthNbr }; this.rangeDateSelection({ isBegin: true, date: this.selectedDateRange.begin, jsDate: this.utilService.getDate(this.selectedDateRange.begin), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.begin, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.begin) }); } else { // second selection const firstDateEarlier: boolean = this.utilService.isDateEarlier( { year: month.year, month: month.monthNbr }, this.selectedDateRange.begin ); if (firstDateEarlier) { const _date = this.selectedDateRange.begin; this.selectedDateRange.end = _date; this.rangeDateSelection({ isBegin: false, date: _date, jsDate: this.utilService.getDate(_date), dateFormat, formatted: this.utilService.formatDate(_date, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(_date) }); this.selectedDateRange.begin = { year: month.year, month: month.monthNbr }; this.rangeDateSelection({ isBegin: true, date: this.selectedDateRange.begin, jsDate: this.utilService.getDate(this.selectedDateRange.begin), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.begin, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.begin) }); } else { this.selectedDateRange.end = { year: month.year, month: month.monthNbr }; this.rangeDateSelection({ isBegin: false, date: this.selectedDateRange.end, jsDate: this.utilService.getDate(this.selectedDateRange.end), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.end, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.end) }); } if (!this.opts.showTime) { this.dateChanged( this.utilService.getDateModel( null, this.selectedDateRange, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ), closeSelectorOnDateSelect ); } } } else { this.selectedMonth = month; this.dateChanged( this.utilService.getDateModel( { year: month.year, month: month.monthNbr }, null, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ), showTime ? false : closeSelectorOnDateSelect ); } } toSelectYear(year: { year: number }): void { const { dateFormat, monthLabels, dateRangeDatesDelimiter, closeSelectorOnDateSelect, showTime, returnFormat } = this.opts; if (this.opts.dateRange) { // month range const isBeginYearInitialized: boolean = this.utilService.isInitializedYear(this.selectedDateRange.begin); const isEndYearInitialized: boolean = this.utilService.isInitializedYear(this.selectedDateRange.end); if (isBeginYearInitialized && isEndYearInitialized) { // both already selected - set begin date and reset end date this.selectedDateRange.begin = year; this.selectedDateRange.end = this.utilService.resetDate(); this.rangeDateSelection({ isBegin: true, date: this.selectedDateRange.begin, jsDate: this.utilService.getDate(this.selectedDateRange.begin), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.begin, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.begin) }); } else if (!isBeginYearInitialized) { // begin date this.selectedDateRange.begin = year; this.rangeDateSelection({ isBegin: true, date: this.selectedDateRange.begin, jsDate: this.utilService.getDate(this.selectedDateRange.begin), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.begin, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.begin) }); } else { // second selection const firstDateEarlier: boolean = this.utilService.isDateEarlier(year, this.selectedDateRange.begin); if (firstDateEarlier) { const _date = this.selectedDateRange.begin; this.selectedDateRange.end = _date; this.rangeDateSelection({ isBegin: false, date: _date, jsDate: this.utilService.getDate(_date), dateFormat, formatted: this.utilService.formatDate(_date, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(_date) }); this.selectedDateRange.begin = year; this.rangeDateSelection({ isBegin: true, date: this.selectedDateRange.begin, jsDate: this.utilService.getDate(this.selectedDateRange.begin), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.begin, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.begin) }); } else { this.selectedDateRange.end = year; this.rangeDateSelection({ isBegin: false, date: this.selectedDateRange.end, jsDate: this.utilService.getDate(this.selectedDateRange.end), dateFormat, formatted: this.utilService.formatDate(this.selectedDateRange.end, dateFormat, monthLabels), epoc: this.utilService.getEpocTime(this.selectedDateRange.end) }); } if (!this.opts.showTime) { this.dateChanged( this.utilService.getDateModel( null, this.selectedDateRange, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ), closeSelectorOnDateSelect ); } } } else { this.dateChanged( this.utilService.getDateModel(year, null, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat), showTime ? false : closeSelectorOnDateSelect ); } } monthStartIdx(y: number, m: number): number { // Month start index const d: Date = new Date(); d.setDate(1); d.setMonth(m - 1); d.setFullYear(y); const idx = d.getDay() + this.sundayIdx(); return idx >= 7 ? idx - 7 : idx; } daysInMonth(m: number, y: number): number { // Return number of days of current month return new Date(y, m, 0).getDate(); } daysInPrevMonth(m: number, y: number): number { // Return number of days of the previous month const d: Date = this.getDate(y, m, 1); d.setMonth(d.getMonth() - 1); return this.daysInMonth(d.getMonth() + 1, d.getFullYear()); } isCurrDay(d: number, m: number, y: number, cmo: number, today: IMyDate): boolean { // Check is a given date the today return d === today.day && m === today.month && y === today.year && cmo === MonthId.curr; } getWidth() { const hasShortCuts = this.opts.shortcuts && this.opts.shortcuts.length > 0; if (this.opts.dateRange && this.opts.showType !== 4) { return hasShortCuts ? '660px' : '574px'; } else { return hasShortCuts ? '380px' : '287px'; } } getToday(): IMyDate { const date: Date = new Date(); if (this.opts.showTime) { return { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate(), hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds() }; } else { return { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() }; } } getDayNumber(date: IMyDate): number { // Get day number: su=0, mo=1, tu=2, we=3 ... const d: Date = this.getDate(date.year, date.month, date.day); return d.getDay(); } getWeekday(date: IMyDate): string { // Get weekday: su, mo, tu, we ... return this.weekDayOpts[this.getDayNumber(date)]; } getDate(year: number, month: number, day: number): Date { // Creates a date object from given year, month and day return new Date(year, month - 1, day, 0, 0, 0, 0); } sundayIdx(): number { // Index of Sunday day return this.dayIdx > 0 ? 7 - this.dayIdx : 0; } generateCalendar(m: number, y: number, notifyChange: boolean, isSecondCalendar?: boolean): void { if (!isSecondCalendar) { this.dates.length = 0; } else { this.dates_range.length = 0; } const today: IMyDate = this.getToday(); const monthStart: number = this.monthStartIdx(y, m); const dInThisM: number = this.daysInMonth(m, y); const dInPrevM: number = this.daysInPrevMonth(m, y); let dayNbr = 1; let cmo: number = MonthId.prev; for (let i = 1; i < 7; i++) { const week: Array = []; if (i === 1) { // First week const pm = dInPrevM - monthStart + 1; // Previous month for (let j = pm; j <= dInPrevM; j++) { const date: IMyDate = { year: m === 1 ? y - 1 : y, month: m === 1 ? 12 : m - 1, day: j }; week.push({ dateObj: date, cmo, currDay: this.isCurrDay(j, m, y, cmo, today), disabled: this.utilService.isDisabledDate(date, this.opts), markedDate: this.utilService.isMarkedDate(date, this.opts.markDates, this.opts.markWeekends), highlight: this.utilService.isHighlightedDate( date, this.opts.sunHighlight, this.opts.satHighlight, this.opts.highlightDates ) }); } cmo = MonthId.curr; // Current month const daysLeft: number = 7 - week.length; for (let j = 0; j < daysLeft; j++) { const date: IMyDate = { year: y, month: m, day: dayNbr }; week.push({ dateObj: date, cmo, currDay: this.isCurrDay(dayNbr, m, y, cmo, today), disabled: this.utilService.isDisabledDate(date, this.opts), markedDate: this.utilService.isMarkedDate(date, this.opts.markDates, this.opts.markWeekends), highlight: this.utilService.isHighlightedDate( date, this.opts.sunHighlight, this.opts.satHighlight, this.opts.highlightDates ) }); dayNbr++; } } else { // Rest of the weeks for (let j = 1; j < 8; j++) { if (dayNbr > dInThisM) { // Next month dayNbr = 1; cmo = MonthId.next; } const date: IMyDate = { year: cmo === MonthId.next && m === 12 ? y + 1 : y, month: cmo === MonthId.curr ? m : cmo === MonthId.next && m < 12 ? m + 1 : 1, day: dayNbr }; week.push({ dateObj: date, cmo, currDay: this.isCurrDay(dayNbr, m, y, cmo, today), disabled: this.utilService.isDisabledDate(date, this.opts), markedDate: this.utilService.isMarkedDate(date, this.opts.markDates, this.opts.markWeekends), highlight: this.utilService.isHighlightedDate( date, this.opts.sunHighlight, this.opts.satHighlight, this.opts.highlightDates ) }); dayNbr++; } } const weekNbr: number = this.opts.showWeekNumbers && this.opts.firstDayOfWeek === MO ? this.utilService.getWeekNumber(week[0].dateObj) : 0; if (!isSecondCalendar) { this.dates.push({ week, weekNbr, year: y }); } else { this.dates_range.push({ week, weekNbr, year: y }); } } this.setDateViewHeaderBtnDisabledState(m, y, isSecondCalendar); if (notifyChange) { // Notify parent this.calendarViewChanged({ year: y, month: m, first: { number: 1, weekday: this.getWeekday({ year: y, month: m, day: 1 }) }, last: { number: dInThisM, weekday: this.getWeekday({ year: y, month: m, day: dInThisM }) } }); } } setDateViewHeaderBtnDisabledState(m: number, y: number, isSecondCalendar: boolean): void { let dpm = false; let dnm = false; const { disableUntil, disableSince, minYear, maxYear } = this.opts; dpm = this.utilService.isMonthDisabledByDisableUntil( { year: m === 1 ? y - 1 : y, month: m === 1 ? 12 : m - 1, day: this.daysInMonth(m === 1 ? 12 : m - 1, m === 1 ? y - 1 : y) }, disableUntil ); dnm = this.utilService.isMonthDisabledByDisableSince( { year: m === 12 ? y + 1 : y, month: m === 12 ? 1 : m + 1, day: 1 }, disableSince ); if (!isSecondCalendar) { this.prevViewDisabled = (m === 1 && y === minYear) || dpm; this.nextViewDisabled = (m === 12 && y === maxYear) || dnm; this.prevDobViewDisabled = y === minYear || dpm; this.nextDobViewDisabled = y === maxYear || dnm; } else { this.prevViewDisabled_range = (m === 1 && y === minYear) || dpm; this.nextViewDisabled_range = (m === 12 && y === maxYear) || dnm; this.prevDobViewDisabled_range = y === minYear || dpm; this.nextDobViewDisabled_range = y === maxYear || dnm; } } setMonthViewHeaderBtnDisabledState(y: number, isSecondCalendar: boolean): void { let dpm = false; let dnm = false; const { disableUntil, disableSince, minYear, maxYear } = this.opts; dpm = this.utilService.isMonthDisabledByDisableUntil({ year: y - 1, month: 12, day: 31 }, disableUntil); dnm = this.utilService.isMonthDisabledByDisableSince({ year: y + 1, month: 1, day: 1 }, disableSince); if (!isSecondCalendar) { this.prevViewDisabled = y === minYear || dpm; this.nextViewDisabled = y === maxYear || dnm; this.prevDobViewDisabled = y === minYear || dpm; this.nextDobViewDisabled = y === maxYear || dnm; } else { this.prevViewDisabled_range = y === minYear || dpm; this.nextViewDisabled_range = y === maxYear || dnm; this.prevDobViewDisabled_range = y === minYear || dpm; this.nextDobViewDisabled_range = y === maxYear || dnm; } } setYearViewHeaderBtnDisabledState(yp: number, yn: number, isSecondCalendar: boolean): void { let dpy = false; let dny = false; const { disableUntil, disableSince, minYear, maxYear } = this.opts; dpy = this.utilService.isMonthDisabledByDisableUntil({ year: yp - 1, month: 12, day: 31 }, disableUntil); dny = this.utilService.isMonthDisabledByDisableSince({ year: yn + 1, month: 1, day: 1 }, disableSince); if (!isSecondCalendar) { this.prevViewDisabled = yp <= minYear || dpy; this.nextViewDisabled = yn >= maxYear || dny; this.prevDobViewDisabled = yp <= minYear || dpy; this.nextDobViewDisabled = yn >= maxYear || dny; } else { this.prevViewDisabled_range = yp <= minYear || dpy; this.nextViewDisabled_range = yn >= maxYear || dny; this.prevDobViewDisabled_range = yp <= minYear || dpy; this.nextDobViewDisabled_range = yn >= maxYear || dny; } } onContainerClick(event: Event) { event.stopPropagation(); } onClickTimeBtn(event: Event) { event.stopPropagation(); if (this.opts.dateRange) { const beginIsInitializedDate = this.utilService.isInitializedDate(this.selectedDateRange.begin); const endIsInitializedDate = this.utilService.isInitializedDate(this.selectedDateRange.end); if (!beginIsInitializedDate || !endIsInitializedDate) { const now = new Date(); // 直接点击确定显示本月和下月 if (!beginIsInitializedDate) { this.selectedDateRange.begin = { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() }; } let endYear = now.getFullYear(); let endmonth = now.getMonth() + 1; if (endmonth >= 12) { endYear = endYear + 1; endmonth = 1; } // else { // endmonth = endmonth + this.opts.monthRangeValue; // } this.selectedDateRange.end = { ...this.selectedDateRange.begin }; // this.selectedDateRange.end = { year: endYear, month: endmonth, day: now.getDate() }; // 点击selectTime之前给dateRange赋两个时间值 this.timeVlaue = this.getTimeStr(now); this.timeVlaue_range = this.getTimeStr(now); } } else { if (!this.utilService.isInitializedDate(this.selectedDate)) { const now = new Date(); // 点击selectTime之前赋值 this.timeVlaue = this.getTimeStr(now); this.selectedDate = { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() }; } } if (!this.timeVlaue) { const now = new Date(); // 点击selectTime之前赋值 this.timeVlaue = this.getTimeStr(now); if (!this.utilService.isInitializedDate(this.selectedDate)) { this.selectedDate = { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() }; } } if (this.selectYear) { this.selectYear = false; } if (this.selectMonth) { this.selectMonth = false; } if (this.selectYear_range) { this.selectYear_range = false; } if (this.selectMonth_range) { this.selectMonth_range = false; } this.selectTime = !this.selectTime; this.cdr.detectChanges(); } private getTimeValue(isDateRange) { const t = { start: null, end: null }; if (this.timeVlaue) { const timeArr = this.timeVlaue.replace('时', ':').replace('分', ':').replace('秒', '').split(':'); if (timeArr.length >= 2) { t.start = { hour: timeArr[0], minute: timeArr[1], second: timeArr[2] ? timeArr[2] : 0 }; } } else { const nowDate = new Date(); const hour = nowDate.getHours(); const minute = nowDate.getMinutes(); const second = nowDate.getSeconds(); if (this.opts.dateRange) { t.start = { hour: 0, minute: 0, second: 0 }; } else { t.start = { hour, minute, second }; } } if (isDateRange) { if (this.timeVlaue_range) { const timeArr_range = this.timeVlaue_range.replace('时', ':').replace('分', ':').replace('秒', '').split(':'); if (timeArr_range.length >= 2) { t.end = { hour: timeArr_range[0], minute: timeArr_range[1], second: timeArr_range[2] ? timeArr_range[2] : 0 }; } } else { const hour = 23; const minute = 59; const second = 59; t.end = { hour, minute, second }; } } return t; } onClickOkBtn(event: Event) { event.stopPropagation(); let timeObj = null; let timeObj_range = null; let selectedDate = null; let selectedDate_range = null; if (this.opts.showTime) { const { start, end } = this.getTimeValue(this.opts.dateRange); timeObj = start; timeObj_range = end; } const { dateFormat, monthLabels, dateRangeDatesDelimiter, closeSelectorOnDateSelect, returnFormat } = this.opts; if (!this.opts.dateRange) { selectedDate = { ...this.initializedDate(this.selectedDate), ...timeObj }; const isInDisableRange = this.utilService.isDisabledDate(selectedDate, this.opts); const earlier = this.utilService.isDateSameOrEarlier(selectedDate, this.opts.disableUntil); selectedDate = !isInDisableRange ? selectedDate : { ...selectedDate, ...(earlier ? this.opts.disableUntil : this.opts.disableSince) }; } else { const begin = { ...this.initializedDate(this.selectedDateRange.begin), ...timeObj }; const end = { ...this.initializedDate(this.selectedDateRange.end, begin), ...timeObj_range }; selectedDate_range = { begin, end }; } const dateModel: IMyDateModel = this.utilService.getDateModel( selectedDate, selectedDate_range, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ); this.dateChanged(dateModel, closeSelectorOnDateSelect); } initializedDate(date: IMyDate, otherDate: IMyDate = { year: 0, month: 0, day: 0 }): IMyDate { const daysInMonth: Array = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; if (!this.utilService.isInitializedDate(date) && !this.utilService.isInitializedDate(otherDate)) { const year = new Date().getFullYear(); const month = new Date().getMonth() + 1; const day = new Date().getDate(); return this.utilService.isDisabledDate({ year, month, day }, this.opts) ? this.opts.disableUntil : { year, month, day }; } else if (!this.utilService.isInitializedDate(date)) { const year = otherDate.month + 1 > 12 ? otherDate.year + 1 : otherDate.year; let month = otherDate.month + 1 > 12 ? 1 : otherDate.month + this.opts.monthRangeValue; if (!date.month) { month = otherDate.month; } const day = otherDate.day < 1 || otherDate.day > daysInMonth[month - 1] ? 1 : otherDate.day; return this.utilService.isDisabledDate({ year, month, day }, this.opts) ? this.opts.disableSince : { year, month, day }; } return date; } setTime(date: any) { const { dateFormat, monthLabels, dateRangeDatesDelimiter, closeSelectorOnDateSelect, returnFormat } = this.opts; if (date instanceof Date) { if (this.opts.showType !== 4 && !this.opts.dateRange) { let targetDate: IMyDate; if (this.opts.showTime) { targetDate = { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate(), hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds() }; } else { targetDate = { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() }; } const dateModel: IMyDateModel = this.utilService.getDateModel( targetDate, null, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ); this.dateChanged(dateModel, closeSelectorOnDateSelect); } else { // 启用周选择时 快捷按钮参数为单个日期 const dateModel: IMyDateModel = this.utilService.getDateModel( null, this.utilService.getNowWeekTime(date), dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ); this.dateChanged(dateModel, closeSelectorOnDateSelect); } } else if (date instanceof Object && this.opts.dateRange) { let targetDateRange: IMyDateRange; const { begin, end } = date; if (!begin || !end) { return; } if (this.opts.showTime) { targetDateRange = { begin: { year: begin.getFullYear(), month: begin.getMonth() + 1, day: begin.getDate(), hour: begin.getHours(), minute: begin.getMinutes(), second: begin.getSeconds() }, end: { year: end.getFullYear(), month: end.getMonth() + 1, day: end.getDate(), hour: end.getHours(), minute: end.getMinutes(), second: end.getSeconds() } }; } else { targetDateRange = { begin: { year: begin.getFullYear(), month: begin.getMonth() + 1, day: begin.getDate() }, end: { year: end.getFullYear(), month: end.getMonth() + 1, day: end.getDate() } }; } const dateModel: IMyDateModel = this.utilService.getDateModel( null, targetDateRange, dateFormat, monthLabels, dateRangeDatesDelimiter, returnFormat ); this.dateChanged(dateModel, closeSelectorOnDateSelect); } else { console.warn('参数必须符合要求!'); } } }