2
0
mirror of https://github.com/tenrok/vue2-datepicker.git synced 2026-06-19 11:50:36 +03:00
Files
vue2-datepicker/src/calendar/calendar-panel.js
T
mengxiong10 1325d41225 vue3 base
2020-11-11 16:56:17 +08:00

261 lines
7.4 KiB
JavaScript

import {
getValidDate,
isValidDate,
createDate,
setMonth,
startOfYear,
startOfMonth,
startOfDay,
} from '../util/date';
import TableDate from './table-date';
import TableMonth from './table-month';
import TableYear from './table-year';
export default {
name: 'CalendarPanel',
inject: {
prefixClass: {
default: 'mx',
},
dispatchDatePicker: {
default: () => () => {},
},
},
emits: ['select', 'update:calendar'],
props: {
value: {},
defaultValue: {
default() {
const date = new Date();
date.setHours(0, 0, 0, 0);
return date;
},
},
defaultPanel: {
type: String,
},
disabledDate: {
type: Function,
default: () => false,
},
type: {
type: String,
default: 'date',
},
getClasses: {
type: Function,
default: () => [],
},
showWeekNumber: {
type: Boolean,
default: undefined,
},
titleFormat: {
type: String,
default: 'YYYY-MM-DD',
},
calendar: Date,
// update date when select year or month
partialUpdate: {
type: Boolean,
default: false,
},
},
data() {
const panels = ['date', 'month', 'year'];
const index = Math.max(panels.indexOf(this.type), panels.indexOf(this.defaultPanel));
const panel = index !== -1 ? panels[index] : 'date';
return {
panel,
innerCalendar: new Date(),
};
},
computed: {
innerValue() {
const value = Array.isArray(this.value) ? this.value : [this.value];
const map = {
year: startOfYear,
month: startOfMonth,
date: startOfDay,
};
const start = map[this.type] || map.date;
return value.filter(isValidDate).map(v => start(v));
},
calendarYear() {
return this.innerCalendar.getFullYear();
},
calendarMonth() {
return this.innerCalendar.getMonth();
},
},
watch: {
value: {
immediate: true,
handler: 'initCalendar',
},
calendar: {
handler: 'initCalendar',
},
defaultValue: {
handler: 'initCalendar',
},
},
methods: {
initCalendar() {
let calendarDate = this.calendar;
if (!isValidDate(calendarDate)) {
const { length } = this.innerValue;
calendarDate = getValidDate(length > 0 ? this.innerValue[length - 1] : this.defaultValue);
}
this.innerCalendar = startOfMonth(calendarDate);
},
isDisabled(date) {
return this.disabledDate(new Date(date), this.innerValue);
},
emitDate(date, type) {
if (!this.isDisabled(date)) {
this.$emit('select', date, type, this.innerValue);
// someone need get the first selected date to set range value. (#429)
this.dispatchDatePicker('pick', date, type);
}
},
handleCalendarChange(calendar, type) {
const oldCalendar = new Date(this.innerCalendar);
this.innerCalendar = calendar;
this.$emit('update:calendar', calendar);
this.dispatchDatePicker('calendar-change', calendar, oldCalendar, type);
},
handelPanelChange(panel) {
this.panel = panel;
},
handleSelectYear(year) {
if (this.type === 'year') {
const date = this.getYearCellDate(year);
this.emitDate(date, 'year');
} else {
this.handleCalendarChange(createDate(year, this.calendarMonth), 'year');
this.handelPanelChange('month');
if (this.partialUpdate && this.innerValue.length === 1) {
const date = new Date(this.innerValue[0]);
date.setFullYear(year);
this.emitDate(date, 'year');
}
}
},
handleSelectMonth(month) {
if (this.type === 'month') {
const date = this.getMonthCellDate(month);
this.emitDate(date, 'month');
} else {
this.handleCalendarChange(createDate(this.calendarYear, month), 'month');
this.handelPanelChange('date');
if (this.partialUpdate && this.innerValue.length === 1) {
const date = new Date(this.innerValue[0]);
date.setFullYear(this.calendarYear);
this.emitDate(setMonth(date, month), 'month');
}
}
},
handleSelectDate(date) {
this.emitDate(date, this.type === 'week' ? 'week' : 'date');
},
getMonthCellDate(month) {
return createDate(this.calendarYear, month);
},
getYearCellDate(year) {
return createDate(year, 0);
},
getDateClasses(cellDate) {
const notCurrentMonth = cellDate.getMonth() !== this.calendarMonth;
const classes = [];
if (cellDate.getTime() === new Date().setHours(0, 0, 0, 0)) {
classes.push('today');
}
if (notCurrentMonth) {
classes.push('not-current-month');
}
const state = this.getStateClass(cellDate);
if (!(state === 'active' && notCurrentMonth)) {
classes.push(state);
}
return classes.concat(this.getClasses(cellDate, this.innerValue, classes.join(' ')));
},
getMonthClasses(month) {
if (this.type !== 'month') {
return this.calendarMonth === month ? 'active' : '';
}
const classes = [];
const cellDate = this.getMonthCellDate(month);
classes.push(this.getStateClass(cellDate));
return classes.concat(this.getClasses(cellDate, this.innerValue, classes.join(' ')));
},
getYearClasses(year) {
if (this.type !== 'year') {
return this.calendarYear === year ? 'active' : '';
}
const classes = [];
const cellDate = this.getYearCellDate(year);
classes.push(this.getStateClass(cellDate));
return classes.concat(this.getClasses(cellDate, this.innerValue, classes.join(' ')));
},
getStateClass(cellDate) {
if (this.isDisabled(cellDate)) {
return 'disabled';
}
if (this.innerValue.some(v => v.getTime() === cellDate.getTime())) {
return 'active';
}
return '';
},
getWeekState(row) {
if (this.type !== 'week') return '';
const start = row[0].getTime();
const end = row[6].getTime();
const active = this.innerValue.some(v => {
const time = v.getTime();
return time >= start && time <= end;
});
return active ? `${this.prefixClass}-active-week` : '';
},
},
render() {
const { panel, innerCalendar } = this;
if (panel === 'year') {
return (
<TableYear
calendar={innerCalendar}
getCellClasses={this.getYearClasses}
onSelect={this.handleSelectYear}
onChangecalendar={this.handleCalendarChange}
/>
);
}
if (panel === 'month') {
return (
<TableMonth
calendar={innerCalendar}
getCellClasses={this.getMonthClasses}
onSelect={this.handleSelectMonth}
onChangepanel={this.handelPanelChange}
onChangecalendar={this.handleCalendarChange}
/>
);
}
return (
<TableDate
class={{ [`${this.prefixClass}-calendar-week-mode`]: this.type === 'week' }}
calendar={innerCalendar}
getCellClasses={this.getDateClasses}
getRowClasses={this.getWeekState}
titleFormat={this.titleFormat}
showWeekNumber={
typeof showWeekNumber === 'boolean' ? this.showWeekNumber : this.type === 'week'
}
onSelect={this.handleSelectDate}
onChangepanel={this.handelPanelChange}
onChangecalendar={this.handleCalendarChange}
/>
);
},
};