Files
.exyone.me-html-homepage/calendar.html
2025-12-08 04:42:44 +00:00

209 lines
9.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>日历组件</title>
<link rel="stylesheet" href="../../assets/css/widgets.css">
</head>
<body>
<div class="widget glass calendar-widget">
<div class="calendar-header">
<button class="calendar-nav" id="prev-month">&lt;</button>
<h3 id="current-month-year">2024年1月</h3>
<button class="calendar-nav" id="next-month">&gt;</button>
</div>
<div class="calendar-grid">
<!-- 星期标题 -->
<div class="calendar-weekday"></div>
<div class="calendar-weekday"></div>
<div class="calendar-weekday"></div>
<div class="calendar-weekday"></div>
<div class="calendar-weekday"></div>
<div class="calendar-weekday"></div>
<div class="calendar-weekday"></div>
<!-- 日期单元格将通过JavaScript动态生成 -->
</div>
</div>
<script>
// 日历功能 - 重构版本
(function() {
let currentDate = new Date();
let selectedDate = null;
// 渲染日历函数
function renderCalendar() {
try {
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
// 更新月份标题
const titleElement = document.getElementById('current-month-year');
if (titleElement) {
titleElement.textContent = `${year}${month + 1}`;
}
// 获取日历网格容器
const calendarGrid = document.querySelector('.calendar-grid');
if (!calendarGrid) {
console.error('日历网格容器未找到');
return;
}
// 保留星期标题,移除所有日期单元格
const weekdayHeaders = Array.from(calendarGrid.querySelectorAll('.calendar-weekday'));
calendarGrid.innerHTML = '';
// 重新添加星期标题
weekdayHeaders.forEach(header => calendarGrid.appendChild(header));
// 获取当月第一天和最后一天
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const daysInMonth = lastDay.getDate();
const startingDay = firstDay.getDay();
// 获取今天的日期用于比较
const today = new Date();
// 添加上月的最后几天
const prevMonthLastDay = new Date(year, month, 0).getDate();
for (let i = startingDay - 1; i >= 0; i--) {
const dayDiv = createDayElement(prevMonthLastDay - i, false);
dayDiv.classList.add('other-month');
calendarGrid.appendChild(dayDiv);
}
// 添加当月的天数
for (let i = 1; i <= daysInMonth; i++) {
const dayDiv = createDayElement(i, true);
dayDiv.setAttribute('data-date', `${year}-${month + 1}-${i}`);
// 高亮今天
if (i === today.getDate() && month === today.getMonth() && year === today.getFullYear()) {
dayDiv.classList.add('today');
}
// 高亮选中的日期
if (selectedDate && i === selectedDate.getDate() && month === selectedDate.getMonth() && year === selectedDate.getFullYear()) {
dayDiv.classList.add('selected');
}
calendarGrid.appendChild(dayDiv);
}
// 添加下月的开始几天确保日历始终显示6行
const totalCells = 42; // 6行7列 = 42个单元格包括星期标题
const currentCells = 7 + startingDay + daysInMonth; // 7个星期标题 + 上月天数 + 当月天数
const remainingDays = totalCells - currentCells;
for (let i = 1; i <= remainingDays; i++) {
const dayDiv = createDayElement(i, false);
dayDiv.classList.add('other-month');
calendarGrid.appendChild(dayDiv);
}
} catch (error) {
console.error('渲染日历出错:', error);
}
}
// 创建日期元素
function createDayElement(day, isCurrentMonth) {
const dayDiv = document.createElement('div');
dayDiv.className = 'calendar-day';
dayDiv.textContent = day;
// 只有当前月的日期可以点击选择
if (isCurrentMonth) {
dayDiv.addEventListener('click', () => handleDayClick(day));
dayDiv.setAttribute('tabindex', '0'); // 使其可聚焦
dayDiv.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleDayClick(day);
e.preventDefault();
}
});
}
return dayDiv;
}
// 处理日期点击
function handleDayClick(day) {
try {
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
selectedDate = new Date(year, month, day);
// 触发日期选择事件
const event = new CustomEvent('date-selected', {
detail: { date: selectedDate }
});
document.dispatchEvent(event);
// 重新渲染以更新选中状态
renderCalendar();
} catch (error) {
console.error('处理日期点击出错:', error);
}
}
// 绑定导航按钮事件
function bindNavigationEvents() {
try {
const prevButton = document.getElementById('prev-month');
const nextButton = document.getElementById('next-month');
if (prevButton) {
prevButton.addEventListener('click', () => {
currentDate.setMonth(currentDate.getMonth() - 1);
renderCalendar();
});
}
if (nextButton) {
nextButton.addEventListener('click', () => {
currentDate.setMonth(currentDate.getMonth() + 1);
renderCalendar();
});
}
// 添加键盘导航
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') {
currentDate.setMonth(currentDate.getMonth() - 1);
renderCalendar();
} else if (e.key === 'ArrowRight') {
currentDate.setMonth(currentDate.getMonth() + 1);
renderCalendar();
}
});
} catch (error) {
console.error('绑定导航事件出错:', error);
}
}
// 初始化日历
function initCalendar() {
try {
bindNavigationEvents();
renderCalendar();
} catch (error) {
console.error('初始化日历出错:', error);
}
}
// 当DOM加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCalendar);
} else {
initCalendar();
}
})();
</script>
</body>
</html>