UNPKG

calendar-lite

Version:
245 lines (210 loc) 7.1 kB
import utils from './utils'; import s from './calendar.scss'; const TOTAL_DAYS = 42; // 日历一共显示42天 const DEFAULT_FORMAT = 'yyyy/MM/dd'; const today = utils.dateFormat(new Date(), DEFAULT_FORMAT); class Calendar { constructor(options) { const defaultOptions = { currentDate: today, format: DEFAULT_FORMAT, monthFormat: 'yyyy年MM月', chooseDate: '' }; if (options.currentDate) { defaultOptions.chooseDate = utils.dateFormat( new Date(options.currentDate), DEFAULT_FORMAT ); } this.options = { ...defaultOptions, ...options }; this.init(); } init() { this.renderContainer(); this.renderController(); this.renderContent(); } renderContainer() { const { el } = this.options; const containerEl = utils.createElement('div', s.container); this.options.containerEl = containerEl; el.appendChild(containerEl); } renderController() { const { containerEl } = this.options; const controllerEl = utils.createElement('div', s.controller); const showMonthEl = utils.createElement('div', s.showMonth); const prevArrow = utils.createElement('button', s.controllerArrow); prevArrow.onclick = () => this.switchMonth('prev'); const nextArrow = utils.createElement( 'button', `${s.controllerArrow} ${s.nextArrow}` ); nextArrow.onclick = () => this.switchMonth('next'); this.options.showMonthEl = showMonthEl; this.handelShowMonth(); controllerEl.appendChild(prevArrow); controllerEl.appendChild(showMonthEl); controllerEl.appendChild(nextArrow); containerEl.appendChild(controllerEl); } renderContent() { const { containerEl } = this.options; const contentEl = utils.createElement('div', s.content); const daysEl = utils.createElement('div'); this.options.daysEl = daysEl; this.renderDays(); contentEl.innerHTML = this.renderWeeks(); contentEl.appendChild(daysEl); containerEl.appendChild(contentEl); } renderWeeks() { const weeks = ['日', '一', '二', '三', '四', '五', '六']; const renderWeek = weeks.map(week => { return `<span class=${s.weekItem}>${week}</span>`; }); const weeksEl = `<div class=${s.weekBox}>${renderWeek.join('')}</div>`; return weeksEl; } renderDays() { const { chooseDate, daysEl } = this.options; const days = this.generateCalendarGroup(); const box = utils.createElement('div', s.dayBox); days.forEach(day => { let dayItemClass = s.dayItem; const dayValue = day.value; if (day.type !== 'current') { dayItemClass = `${dayItemClass} ${s.blurDay}`; } if (dayValue === today) { dayItemClass = `${dayItemClass} ${s.today}`; } if (dayValue === chooseDate) { dayItemClass = `${dayItemClass} ${s.chooseDate}`; } const dayEl = utils.createElement('button', dayItemClass); dayEl.innerHTML = `<div class=${s.dayItemContainer}> <span class=${s.dayItemText}>${day.text}</span></div>`; dayEl.onclick = () => this.chooseDate(dayEl, dayValue); box.appendChild(dayEl); }); const replacedNode = daysEl.firstChild; if (replacedNode) { daysEl.replaceChild(box, replacedNode); } else { daysEl.appendChild(box); } } generateCalendarGroup() { let { currentDate } = this.options; currentDate = new Date(currentDate); const prevMonthDate = new Date(this.switchMonthOfDate('prev')); const nextMonthDate = new Date(this.switchMonthOfDate('next')); const currentYear = currentDate.getFullYear(); const currentMonth = currentDate.getMonth() + 1; const prevMonthYear = prevMonthDate.getFullYear(); const prevMonthMonth = prevMonthDate.getMonth() + 1; const nextMonthYear = nextMonthDate.getFullYear(); const nextMonthMonth = nextMonthDate.getMonth() + 1; const currentMonthDays = new Date(currentYear, currentMonth, 0).getDate(); // 获取本月天数 const weekOfCurrentMonth = new Date( `${currentYear}/${utils.formatNumber(currentMonth)}/01` ).getDay(); // 获取本月第一天星期几 const prevMonthDays = new Date(prevMonthYear, prevMonthMonth, 0).getDate(); // 获取上月天数 const dayList = []; // 生成上个月的日期 for (let i = 0; i < weekOfCurrentMonth; i++) { const text = prevMonthDays - i; const value = `${prevMonthYear}/${utils.formatNumber( prevMonthMonth )}/${utils.formatNumber(text)}`; const item = { text, type: 'prev', value }; dayList.push(item); } dayList.reverse(); // 生成本月的日期 for (let i = 1; i <= currentMonthDays; i++) { const text = i; const value = `${currentYear}/${utils.formatNumber( currentMonth )}/${utils.formatNumber(text)}`; const item = { text, type: 'current', value }; dayList.push(item); } // 生成下个月的日期 for (let i = 1; dayList.length < TOTAL_DAYS; i++) { const text = i; const value = `${nextMonthYear}/${utils.formatNumber( nextMonthMonth )}/${utils.formatNumber(text)}`; const item = { text, type: 'next', value }; dayList.push(item); } return dayList; } chooseDate(el, date) { const { onDayClick, format } = this.options; this.options.chooseDate = date; this.options.currentDate = date; const chooseDateEl = document.getElementsByClassName(s.chooseDate)[0]; chooseDateEl && chooseDateEl.classList.remove(s.chooseDate); el.classList.add(s.chooseDate); onDayClick && onDayClick(utils.dateFormat(new Date(date), format)); } switchMonth(action) { this.options.currentDate = this.switchMonthOfDate(action); this.handelShowMonth(); this.renderDays(); } switchMonthOfDate(action) { let { currentDate, onClickPreMonth, onClickNextMonth, onMonthChange } = this.options; currentDate = new Date(currentDate); const currentYear = currentDate.getFullYear(); const currentMonth = currentDate.getMonth() + 1; let newMonth, newYear; if (action === 'prev') { newMonth = currentMonth - 1; newYear = currentYear; if (newMonth < 1) { newYear = currentYear - 1; newMonth = 12; } onClickPreMonth && onClickPreMonth(); } else if (action === 'next') { newMonth = currentMonth + 1; newYear = currentYear; if (newMonth > 12) { newYear = currentYear + 1; newMonth = 1; } onClickNextMonth && onClickNextMonth(); } onMonthChange && onMonthChange(); const newDate = `${newYear}/${utils.formatNumber(newMonth)}/01`; return newDate; } handelShowMonth() { const { showMonthEl, currentDate, monthFormat } = this.options; const showMonth = utils.dateFormat(new Date(currentDate), monthFormat); showMonthEl.textContent = showMonth; } } export default Calendar;