This calendar control is similar to the calendar used by Yuanzi, as shown below:
This kind of calendar control is not difficult to implement. Here is a brief analysis of my ideas:
First, it is the configurable items of the control:
...
settings:
{
firstDayOfWeek: 1,
baseClass: "calendar",
curDayClass: "curDay",
prevMonthCellClass: " prevMonth",
nextMonthCellClass: "nextMonth",
curMonthNormalCellClass: "",
prevNextMonthDaysVisible: true
},
...
weekDayNames: [],
.. .
Half of them are used to control cell styles (without too much description), and the others (firstDayOfWeek, prevNextMonthDaysVisible, weekDayNames) have the following meanings:
firstDayOfWeek: calendar starts with The day of the week as the first day
prevNextMonthDaysVisible: Whether to display dates other than this month
weekDayNames: the name of the week (an array starting from 1, the value at 1 will be used as the display name of Monday, so By analogy)
Next, enter the stage of generating html code:
1. Generate calendar header:
_RenderTitle: function(month, year) {
var ht = [];
//Date
ht.push("
");
ht.push("< ", year, "year", month, "month > | ");
ht.push("
");
//Week
ht.push("
");
for (var i = 0; i < 7; i ) {
var day = (i this.settings.firstDayOfWeek) == 7 ? 7: (i this.settings.firstDayOfWeek) % 7;
ht.push("", this.weekDayNames[day], " | ")
}
ht.push("
");
return ht.join("");
},
The date part is the id of the operation 'button' using the calendar The id of the control container is used as a prefix to ensure that the id is unique.
The week part gets weekDayName based on the setting of firstDayOfWeek. The key here is to determine the day of the week that each cell represents. The idea is very simple:
var day = (i this.settings.firstDayOfWeek) == 7 ? 7 : (i this.settings.firstDayOfWeek) % 7;
In this way, you can get the week represented by the current cell.
2. Generate the main part of the calendar:
_RenderBody: function(month, year) {
var date = new Date(year, month - 1, 1);
var day = date.getDay();
var dayOfMonth = 1;
var daysOfPrevMonth = (7 - this.settings.firstDayOfWeek day) % 7;
var totalDays = this._GetTotalDays(month, year);
var totalDaysOfPrevMonth = this._GetToalDaysOfPrevMonth(month, year);
var ht = [];
var curDate;
for (var i = 0; ; i ) {
curDate = null;
if (i % 7 == 0) {//新起一行
ht.push("
");
}
ht.push("if (i >= daysOfPrevMonth && dayOfMonth <= totalDays) {//本月 curDate = new Date(year, month - 1, dayOfMonth); if (Date.parse(new Date().toDateString()) - curDate == 0) { ht.push(" class='", this.settings.curDayClass, "'"); } else { ht.push(" class='", this.settings.curMonthNormalCellClass, "'"); } dayOfMonth ; } else if (i < daysOfPrevMonth) {//上月 if (this.settings.prevNextMonthDaysVisible) { var prevMonth = month; var prevYear = year; if (month == 1) { prevMonth = 12; prevYear = prevYear - 1; } else { prevMonth = prevMonth - 1; } curDate = new Date(prevYear, prevMonth - 1, totalDaysOfPrevMonth - (daysOfPrevMonth - i - 1)); ht.push(" class='", this.settings.prevMonthCellClass, "'"); } } else {//下月 if (this.settings.prevNextMonthDaysVisible) { var nextMonth = month; var nextYear = year; if (month == 12) { nextMonth = 1; nextYear = prevYear 1; } else { nextMonth = nextMonth 1; } curDate = new Date(nextYear, nextMonth-1, i - dayOfMonth - daysOfPrevMonth 2); ht.push(" class='", this.settings.nextMonthCellClass, "'"); } } ht.push(">"); ht.push(this._BuildCell(curDate)); ht.push(" | ");
if (i % 7 == 6) {//结束一行
ht.push("
");
}
if (i % 7 == 6 && dayOfMonth - 1 >= totalDays) {
break;
}
}
return ht.join("");
},
(1).获取该月一号代表星期几。这样才能判断1号应该放到哪个单元格,也就是该月从哪个单元格开始(创建日期的时候month减了1,这是由于js Date对象本身的特性)。
(2).定义了一个标识变量 dayOfMonth ,用于控制本月日期显示区域。
(3).计算要展示的上月的天数以及上月的总天数(不用计算下月要展示的天数和总天数,因为下月要展示的日期是从1开始,最多不会超过6)。
(4).显示本月的日期:
条件i >= daysOfPrevMonth && dayOfMonth <= totalDays决定了本月日期的显示区域。
(5).显示上月日期:
当i < daysOfPrevMonth 时即为上月日期的显示区域。
(6). (4)、(5)之外当然就是下月日期的显示区域了。
(7).何时结束:
从代码看到for循环是没有终止条件的,因此必须自己决定何时退出循环:
if (i % 7 == 6 && dayOfMonth - 1 >= totalDays) {
break;
}
i % 7 == 6表示一行结束, dayOfMonth - 1 >= totalDays表示本月日期已经展示完毕。
(8).构造curDate:
curDate代表每个单元格对应的日期。
在显示本月日期时, curDate = new Date(year, month - 1, dayOfMonth);
在显示上月日期时, curDate = new Date(prevYear, prevMonth-1, totalDaysOfPrevMonth - (daysOfPrevMonth - i - 1));
在显示下月日期时, curDate = new Date(nextYear, nextMonth-1, i - dayOfMonth - daysOfPrevMonth 2),加2是由于i是从0开始,本身就少了1,dayOfMonth 在退出显示本月日期时多加了一次.
最后,再来看看_BuildCell做了什么事情:
_BuildCell: function(curDate) {
var ht = [];
if (curDate) {
for (var j = 0; j < this.dateLinkMappings.length; j ) {
if (Date.parse(this.dateLinkMappings[j].Date) - curDate == 0) {
ht.push("
", curDate.getDate(), "");
break;
}
}
if (j == this.dateLinkMappings.length) {
ht.push(curDate.getDate());
}
}
else {
ht.push(" ");
}
return ht.join ("");
},
In fact, the intention of this calendar control is that the user can pass in the mapping array of the date and the link corresponding to the date during initialization, which is this. dateLinkMappings, when constructing a cell, if the date being constructed is included in this.dateLinkMappings, the current cell will be constructed into the form of
, otherwise it will be in the form of ordinary text.
OK, the implementation logic is roughly the same. Let’s take a look at the demonstration effect at the end of the article:
The front-end calling code is as follows:
var date = new Date();
var mapping = [];
mapping.push(new DateLinkMapping("3-22-2010" , "javascript:alert(1)"));
mapping.push(new DateLinkMapping("4-1-2010", "javascript:alert(1)"))
Calendar.Init(null, mapping );
Calendar.RenderCalendar("myCalendar", date.getMonth() 1, date.getFullYear());
Package download address Statement:The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn