跳转到内容
aswind7
GitHub
Blog

日历面板

原生实现的日历面板组件

点击查看演示效果: demo

核心算法


// 原型函数
Calendar.prototype.init = function() {
	var calendarDOM = this.dom;
	var panelDOM = this.panelDOM;
	var calendarInput = calendarDOM.getElementsByClassName("calendar-input")[0].querySelector("input[type=text]");
	var calendarInputWeekday = calendarDOM.querySelector(".weekdays");
	var calendarInputPrompt = calendarDOM.querySelector(".prompt");
	var calendarPanelTds = panelDOM.querySelectorAll("tbody td");

	// 渲染输入框
	var today = new Date();
	calendarInput.value = today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate();
	// 渲染输入框的工作日
	calendarInputWeekday.innerHTML = calendarLibrary.getWeekday(today);
	// 提醒话语
	calendarInputPrompt.innerHTML = "";
	// 渲染面板上的日期
	panelDOM.querySelector("span.year").innerHTML = today.getFullYear();
	panelDOM.querySelector("span.month").innerHTML = (today.getMonth() + 1);
	// 渲染面板的表格
	calendarLibrary.renderTable(today.getFullYear(), today.getMonth() + 1, panelDOM);
	// 为input绑定函数
	calendarInput.addEventListener("click", function(event) {
		event = event || window.event;
		// 显示日历面板
		panelDOM.style.display = "block";
		// 渲染数据
		var dateObj = calendarLibrary.getDateFromInput(this.value);
		if (dateObj === "格式错误" || !dateObj) {
			calendarInputPrompt.innerHTML = "格式错误";
			calendarInputPrompt.style.display = "block";
			return;
		} else {
			calendarInputPrompt.style.display = "none";
		}
		// 渲染面板上的日期
		panelDOM.querySelector("span.year").innerHTML = dateObj.year;
		panelDOM.querySelector("span.month").innerHTML = dateObj.month;
		// 渲染面板的表格
		calendarLibrary.renderTable(dateObj.year, dateObj.month, panelDOM);
		event.stopPropagation();
	}, false);

	// 为日历对应的面板绑定函数
	panelDOM.addEventListener("click", function(event) {
		event = event || window.event;
		event.stopPropagation();
	}, false);
	calendarPanelTds.forEach(function(elem) {
		elem.addEventListener("click", function(event) {
			event = event || window.event;
			if (this.innerHTML == "") {
				return;
			}
			var year = panelDOM.querySelector("thead .year").innerHTML;
			var month = panelDOM.querySelector("thead .month").innerHTML;
			var day = this.innerHTML;
			var result = year + "-" + month + "-" + day;
			calendarInput.value = result;
			// 工作日
			if (day === "今天") {
				day = (new Date()).getDate();
			}
			var weekdays = calendarLibrary.getWeekday(new Date(year, month - 1, day));
			calendarInputWeekday.innerHTML = weekdays;
			// 隐藏面板
			panelDOM.style.display = "none";
		}, false);
	})

	// 为body绑定函数
	document.body.addEventListener("click", function(event) {
		event = event || window.event;
		// 隐藏日历面板
		panelDOM.style.display = "none";
	}, false);
}


// 按照国外的方式,周日在前面
calendarLibrary.renderTable = function(nowYear, nowMonth, panelDOM) {
	// 渲染表格,先获取此月的第一天是周几,注意月数减一
	var d = new Date(nowYear, nowMonth - 1, 1);
	var weekdayNumber = d.getDay();
	// 获取这个月的天数
	var amountOfDays = (new Date(nowYear, nowMonth, 0)).getDate();
	var daysArray = [];
	var tdsArray = panelDOM.querySelectorAll("tbody td");
	// 把表格清空,重置
	tdsArray.forEach(function(elem) {
		elem.innerHTML = "";
		elem.className = "";
	});
	for (var i = 0; i < amountOfDays; i++) {
		daysArray.push(i + 1);
		tdsArray[i].weekdayNumber = i % 7;
	}
	for (var i = 0; i < tdsArray.length; i++) {
		// 判断前七个是否有空,amountOfDays
		if (i < 7 && i < weekdayNumber) {
			tdsArray[i].className = "no-data";
		} else if (daysArray.length) {
			tdsArray[i].innerHTML = daysArray.shift();
			tdsArray[i].className = "have-data";
			// 判断是否今天
			var today = new Date();
			if (nowYear == today.getFullYear() && nowMonth == today.getMonth() + 1 && tdsArray[i].innerHTML == today.getDate()) {
				tdsArray[i].innerHTML = "今天";
				tdsArray[i].className = "today";
			}
		} else {
			tdsArray[i].className = "no-data";
		}
	}
}