以下是非常流行的用 JavaScript 编写日历的后续内容,其中我用 JavaScript 创建了一个日历小部件。
在继续这篇文章之前,您应该继续 阅读该文章 并熟悉该过程,因为我将使用相同的代码来呈现以下内容。
我将通过允许用户通过单击日期区域和一次拖动多个日期来选择多天来继续实施。
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="calendar.css">
</head>
<body>
<div class="calendar" >
<div class="calendar-btn month-btn" onclick="toggleMonths()">
<span id="curMonth"></span>
<div id="months" class="months dropdown"></div>
</div>
<div class="calendar-btn year-btn" onclick="toggleYears()">
<span id="curYear"></span>
<div id="years" class="years dropdown"></div>
</div>
<div class="clear"></div>
<div class="calendar-dates">
<div class="days">
<div class="day label">一</div>
<div class="day label">二</div>
<div class="day label">三</div>
<div class="day label">四</div>
<div class="day label">五</div>
<div class="day label">六</div>
<div class="day label">日</div>
<div class="clear"></div>
</div>
<div class="days">
</div>
</div>
</div>
<script src="calendar.js" async defer></script>
</body>
</html>
JS
function toggleMonths() {
var cont = document.getElementById('months');
if (cont.style.display == 'block') {
cont.style.display = 'none';
} else {
cont.style.display = 'block';
}
}
function toggleYears() {
var cont = document.getElementById('years');
if (cont.style.display == 'block') {
cont.style.display = 'none';
} else {
cont.style.display = 'block';
}
}
var months = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"];
const curDate = new Date();
const curYear = curDate.getFullYear(); // returns 95
console.log(curYear);
var startYear = curYear - 20;
var endYear = curYear + 20;
var month = 0;
var year = 0;
var selectedDays = new Array();
var mousedown = false;
var mousemove = false;
function loadCalendarMonths() {
for (var i = 0; i < months.length; i++) {
var doc = document.createElement("div");
doc.innerHTML = months[i];
doc.classList.add("dropdown-item");
doc.onclick = (function () {
var selectedMonth = i;
return function () {
month = selectedMonth;
document.getElementById("curMonth").innerHTML = months[month];
loadCalendarDays();
return month;
}
})();
document.getElementById("months").appendChild(doc);
}
}
function loadCalendarYears() {
document.getElementById("years").innerHTML = "";
for (var i = startYear; i <= endYear; i++) {
var doc = document.createElement("div");
doc.innerHTML = i;
doc.classList.add("dropdown-item");
doc.onclick = (function () {
var selectedYear = i;
return function () {
year = selectedYear;
document.getElementById("curYear").innerHTML = year;
loadCalendarDays();
return year;
}
})();
document.getElementById("years").appendChild(doc);
}
}
function ISO_numeric_date(dt)
{
return (dt.getDay() === 0 ? 7 : dt.getDay());
}
function loadCalendarDays() {
document.getElementById("calendarDays").innerHTML = "";
var tmpDate = new Date(year, month, 0);
var num = daysInMonth(month, year);
var dayofweek = ISO_numeric_date(tmpDate); // find where to start calendar day of week
for (var i = 1; i <= dayofweek; i++) {
var d = document.createElement("div");
d.classList.add("day");
d.classList.add("blank");
document.getElementById("calendarDays").appendChild(d);
}
for (var i = 0; i < num; i++) {
var tmp = i + 1;
var d = document.createElement("div");
d.id = "calendarday_" + tmp;
d.className = "day";
d.innerHTML = tmp;
d.dataset.day = tmp;
d.addEventListener('click', function () {
this.classList.toggle('selected');
if (!selectedDays.includes(this.dataset.day))
selectedDays.push(this.dataset.day);
else
selectedDays.splice(selectedDays.indexOf(this.dataset.day), 1);
});
d.addEventListener('mousemove', function (e) {
e.preventDefault();
if (mousedown)
{
this.classList.add('selected');
if (!selectedDays.includes(this.dataset.day))
selectedDays.push(this.dataset.day);
}
console.log(selectedDays);
});
d.addEventListener('mousedown', function (e) {
e.preventDefault();
mousedown = true;
});
d.addEventListener('mouseup', function (e) {
e.preventDefault();
mousedown = false;
});
document.getElementById("calendarDays").appendChild(d);
}
var clear = document.createElement("div");
clear.className = "clear";
document.getElementById("calendarDays").appendChild(clear);
}
function daysInMonth(month, year)
{
var d = new Date(year, month + 1, 0);
return d.getDate();
}
window.addEventListener('load', function () {
var date = new Date();
month = date.getMonth();
year = date.getFullYear();
document.getElementById("curMonth").innerHTML = months[month];
document.getElementById("curYear").innerHTML = year;
loadCalendarMonths();
loadCalendarYears();
loadCalendarDays();
});
CSS
body, *{
padding:0px;
margin:0px;
box-sizing: border-box;
}
.calendar
{
background-color: white;
padding: 20px;
box-shadow: 0px 5px 10px rgba(0,0,0,0.4);
}
.calendar .dropdown
{
display: none;
position: absolute;
background-color: #fff;
color: #1caff6;
text-align: center;
font-size: 14pt;
padding-top: 5px;
padding-bottom: 5px;
padding-left: 30px;
padding-right: 30px;
width: 160px;
left: 0px;
z-index: 2000;
}
.calendar .dropdown .dropdown-item
{
cursor:pointer;
opacity: .7;
transition: .5s opacity;
}
.calendar .dropdown .dropdown-item:hover
{
opacity: 1;
}
.calendar .years
{
display:none;
}
.calendar .title
{
text-align:center;
font-size:20pt;
}
.calendar .calendar-btn
{
float: left;
background-color: #24aeff;
color: white;
text-align: center;
font-size: 14pt;
padding-top: 5px;
padding-bottom: 5px;
position: relative;
width: 20%;
cursor: pointer;
transition: .5s background-color;
}
.calendar .calendar-btn:hover{
background-color:#1f71a1;
}
.calendar .year-btn
{
float:right;
}
.calendar .calendar-dates .days .day
{
float:left;
width: 12%;
margin: 1%;
padding: 1%;
font-size:13pt;
text-align:center;
border-radius: 10px;
border: solid 1px #ddd;
}
.calendar .calendar-dates .days .day.blank
{
background-color: white;
border:none;
}
.calendar .calendar-dates .days .day.selected
{
background-color: #1caff6;
color: white;
cursor:pointer;
opacity: .5;
transition: .5s opacity;
}
.calendar .calendar-dates .days .day.selected:hover
{
opacity: 1;
}
.calendar .calendar-dates .days .day.label
{
height: 40px;
background-color: white;
color: black;
border:none;
font-weight:bold;
}
.clear{
clear:both;
}
@media only screen and (max-width: 960px) {
.calendar{
width: 100%;
margin: 0px;
margin: 0px;
box-sizing: border-box;
position: relative;
left: 0px;
}
}
1. 新变量
我们将需要将以下新变量添加到日历脚本中。
var selectedDays = new Array();
var mousedown = false;
selectedDays数组将用于跟踪日历上当前选定的日期,mousedown布尔表达式将用于监视鼠标的当前状态。本质上,我们想知道在选择多天时我们当前是否处于中间拖动状态。
2. 单日选择
让我们首先允许您的用户在日历上选择一天,这通常是任何在线日历最需要的功能。以下是第 1 部分中的loadCalendarDays() 函数。它有 2 个您需要添加的新功能,即向“day”div 添加新数据集,以便更轻松地检索所选日期。我们将添加 click 事件处理程序,它将负责从 selectedDays
function loadCalendarDays() {
document.getElementById("calendarDays").innerHTML = "";
var tmpDate = new Date(year, month, 0);
var num = daysInMonth(month, year);
var dayofweek = tmpDate.getDay(); // find where to start calendar day of week
for (var i = 0; i <= dayofweek; i++) {
var d = document.createElement("div");
d.classList.add("day");
d.classList.add("blank");
document.getElementById("calendarDays").appendChild(d);
}
for (var i = 0; i < num; i++) {
var tmp = i + 1;
var d = document.createElement("div");
d.id = "calendarday_" + tmp;
d.className = "day";
d.innerHTML = tmp;
d.dataset.day = tmp; // easier to retrieve the date
/* ****************** Click Event ********************** */
d.addEventListener('click', function(){
this.classList.toggle('selected');
if (!selectedDays.includes(this.dataset.day))
selectedDays.push(this.dataset.day);
else
selectedDays.splice(selectedDays.indexOf(this.dataset.day), 1);
});
/* **************************************************** */
document.getElementById("calendarDays").appendChild(d);
}
var clear = document.createElement("div");
clear.className = "clear";
document.getElementById("calendarDays").appendChild(clear);
}
让我们更详细地看一下点击事件。本质上,我们正在向 day 元素添加或删除一个类,这表明它已被选中。我们将检查当前选择的日期是否已经存在于 selectedDays
/* ****************** Click Event ********************** */
d.addEventListener('click', function(){
this.classList.toggle('selected');
if (!selectedDays.includes(this.dataset.day))
selectedDays.push(this.dataset.day);
else
selectedDays.splice(selectedDays.indexOf(this.dataset.day), 1);
});
/* **************************************************** */
多日选择
可以通过在日历中拖动鼠标来选择多天,沿途选择所需的日子。为此,我们将需要 JavaScript 提供的一些鼠标事件处理程序,从mousedown事件开始,然后是mousemove 事件,最后是mouseup事件。
mousedown - mousedown 事件将简单地跟踪鼠标键何时被按住。这将有助于确保我们只选择确实按下鼠标键的日期。
d.addEventListener('mousedown', function(e){
e.preventDefault();
mousedown = true;
});
mouseup - mouseup 事件本质上与 mousedown 事件相同。按下鼠标键后,我们要重置 mousedown 变量,以便它可以停止选择日期。
d.addEventListener('mouseup', function(e){
e.preventDefault();
mousedown = false;
});
mousemove - mousemove 事件是实际发生选择的地方。它与点击事件非常相似。我们要做的第一件事是检查鼠标键当前是否被按下,如果是,则意味着我们正在拖动我们的移动。在这种情况下,我们将希望几乎复制单击事件,除了我们不想切换选择,我们只想确保它们被选中。
d.addEventListener('mousemove', function(e){
e.preventDefault();
if (mousedown)
{
this.classList.add('selected');
if (!selectedDays.includes(this.dataset.day))
selectedDays.push(this.dataset.day);
}
});
请注意,如果您愿意,您也可以在 mousemove 上取消选择日期。
升级
您可以使用日历小部件做很多事情。虽然这是创建具有实际功能的日历版本的良好开端,但您可以更进一步并构建以下任何内容。
- 根据“天数”范围选择
- 选择整月
- 选择整周
在以后的文章中,我将讨论这些功能以及更多内容。