算法:
1. 根据指定年份和月份,计算该月第一天的起始位置和最后一天的结束位置
2.第一个单元格到起始位置,填充上个月日期或空白
3.起始位置和结束位置填充该月日期
4.结束位置之后填充下个月日期或空白
效果图:
JS代码:
var showIds=[];
var selectedId =null;
var selectedMonth = null;
var selectedYear = null;
/**日历初始化,默认当前月份日历
*/
function initCalendar(calendarId){
var date_now = new Date();
initCalendarNew(calendarId, date_now.getFullYear(),date_now.getMonth());
}
/**
* calendarId: 日历容器id
* year:4位年
* month: 0~11
*/
function initCalendarNew(calendarId,year,month){
selectedMonth=month;
selectedYear=year;
var cDate = new Date(Date.parse(year+"/"+(month+1)+"/1"));
var calendar = document.getElementById('calendarId');
if(calendarId){
calendar = document.getElementById(calendarId);
}
if(calendar!=null){
calendar.innerHTML="";
var cTable = document.createElement("table");
calendar.appendChild(cTable);
initCalendarHead(cTable);
//计算month的总天数
var monthDays = getMonthDays(month+1);
//计算月份开始位置
var monthBegin = calcStart(cDate);
//计算月份结束位置
var monthEnd = monthDays+monthBegin;
//最后一行最后一个单元格位置
var end = monthEnd%7==0?monthEnd:monthEnd+(7-monthEnd%7)
var tr = null;
var td = null;
var week = -1;
for(var i=0;i<end;i++){
if(i%7==0){
tr = cTable.insertRow(-1);
tr.style.height=38;
}
td= tr.insertCell(-1);
week = (i+1)%7;
//创建单元格
initCell(td,i-monthBegin,i,i-monthEnd,i>=monthEnd,month,week);
}
}
}
/**
* date 单元格位置与该月份第一天单元格位置的差值
* nextMonthDay 单元格位置该月份最后一天单元格位置的差值
* nextFlag 是否为下个月日期
*/
function initCell(cell,date,days,nextMonthDay,nextFlag,month,week){
//将差值调整为日期。例如:0调整为1号,-1调整为上个月最后一天
date = date+1;
var currentDateFlag = date_now.getDate()==date && month==date_now.getMonth();
var showDaysClass = currentDateFlag?"show_now":"hide";
var previousFlag = false;
if(date<1){
date = getMonthDays(date_now.getMonth())+date;
previousFlag = true;
}
if(nextFlag){
previousFlag = false;
date = nextMonthDay+1;
}
var showCurClass = currentDateFlag?"current_date":((week==0 || week==6)?"rest_date":"normal_date");
cell.className=currentDateFlag?"selected":"";
if(previousFlag){
showCurClass+="_pre";
showDaysClass+="_pre";
}else if(nextFlag){
showCurClass+="_next";
showDaysClass+="_next";
}
//初始化时,如果是今天则设置为选中
selectedId = currentDateFlag?days:selectedId;
cell.align="center";
var daysHtml = days>0?"第"+days+"天":"";
var html = "<div id='"+days+"' οnclick='showDayInfo(this)' οnmοuseenter='showDays(this,"+(currentDateFlag)+")'><label class='"+showCurClass+"'>"+date+"</label><br><label id='label_"+days+"' class='"+showDaysClass+"'>"+daysHtml+"</label></div>";
cell.innerHTML=html;
}
/*初始化日历表头
*/
function initCalendarHead(table){
var tr = table.insertRow(-1);
var td = tr.insertCell(-1);
var year = selectedMonth-1<0?selectedYear-1:selectedYear;
var month = selectedMonth-1<0?selectedMonth+11:selectedMonth-1;
td.innerHTML="<label class='button white' οnclick='initCalendarNew(\"calendar\","+year+","+month+")' style='width:20px'>< </label>";
td.colSpan=2;
td.align="right";
td = tr.insertCell(-1);
td.innerHTML="<label>"+selectedYear+"年"+(selectedMonth+1)+"月</label><label οnclick='initCalendarNew(\"calendar\","+date_now.getFullYear()+","+date_now.getMonth()+")' class='button white'>今天</label>";
td.colSpan=3;
td.align="center";
td = tr.insertCell(-1);
year = selectedMonth+1>11?selectedYear+1:selectedYear;
month = selectedMonth+1>11?selectedMonth-11:selectedMonth+1;
td.innerHTML="<label οnclick='initCalendarNew(\"calendar\","+year+","+month+")' class='button white' style='width:20px'> ></label>";
td.align="left";
td.colSpan=2;
tr = table.insertRow(-1);
tr.height="30px";
var data = ["一","二","三","四","五","六","日"];
for(var i=0;i<data.length;i++){
td = tr.insertCell(-1);
td.width="50px";
td.align="center"
td.innerHTML="<label style='font-size:12px'>周"+data[i]+"</label>";
}
}
function getMonthDays(month){
var monthDays = 31;
if(month ==4 || month==6 || month==9 || month==11) {
monthDays = 30;
}else if(month==2){
monthDays=28;
if((selectedYear%4==0&& selectedYear%100!=0) || selectedYear%400==0){
monthDays = 29;
}
}
return monthDays;
}
function calcStart(date){
var week = date.getDay();
week--;
if(week<0){
week+=7;
}
return week;
}
/**
* 兼容IE
*/
function parseDate(val){
val = val.replace(/-/g,"/");
return Date.parse(val);
}
/**
* 鼠标滑过展示提示
*/
function showDays(div,currentFlag){
if(!currentFlag){
showIds.push(div.id);
var obj = null;
for(var i=0;i<showIds.length;i++){
obj = document.getElementById('label_'+showIds[i]);
if(obj){
obj.className="hide";
}
}
//document.getElementById('label_37').style.display="";
obj = document.getElementById('label_'+div.id);
if(obj){
obj.className="show";
setTimeout(function(){obj.className="hide";showIds.remove(div.id);},1000);
}
}
}
function message(msg){
var msgElement = document.getElementById("msg");
msgElement.innerHTML+=msg+"<br>";
}
function showDayInfo(parentDiv){
clearSelected();
document.getElementById(parentDiv.id).parentNode.className="selected";
selectedId=parentDiv.id;
}
function clearSelected(){
if(selectedId){
if(document.getElementById(selectedId)){
document.getElementById(selectedId).parentNode.className="";
}
}
}
Array.prototype.remove = function(obj){
var length = this.length;
var result = -1;
for(var i=0;i<length; i++){
if(obj==this[i]){
result = i;
this.splice(i,1);
break;
}
}
return result;
}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!---->
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
<title>日历</title>
<link type="text/css" rel="stylesheet" href="babyCalendar.css"></link>
<script type="text/javascript" src="babyCalendar.js"></script>
</head>
<body οnlοad="init();">
<div>
<div id="calendar"></div>
<div id="calendarExt"></div>
</div>
<div id="msg"></div>
</body>
</html>
css文件:
.show,.show_now{
font-size:12px;
color:green;
display:"";
}
.hide ,.hide_pre,.hide_next{
display:none;
}
.rest_date{
font-size:18px;
color:red;
}
.rest_date_pre,.rest_date_next{
font-size:18px;
color:gray;
}
.current_date{
font-size:18px;
color:green;
}
.normal_date{
font-size:18px;
color:blue;
}
.normal_date_pre,.normal_date_next{
font-size:18px;
color:gray;
}
.selected{
background-color:#B0C4DE;
}
div#calendar table,table.thinBorder{
border-collapse:collapse;
border:none;
margin-bottom:5px;
}
div#calendar td{
border:solid #696969 1px;
}
td.thinBorder{
border:solid #696969 1px;
padding:5px 23px 5px 25px;
}
.label_button{
cursor:pointer;
border:solid #696969 1px;
background-image:-webkit-linear-gradient(top,#fff,#999);
display:inline-block;
/*-moz-linear-gradient(top,#000,#fff);
-o-linear-gradient(top,,#000,#fff);*/
}
.button {
display: inline-block;
zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
*display: inline;
vertical-align: baseline;
margin: 0 2px;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: 14px/100% Arial, Helvetica, sans-serif;
padding: 2px 5px 2px;
text-shadow: 0 1px 1px rgba(0,0,0,.3);
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
box-shadow: 0 1px 2px rgba(0,0,0,.2);
}
.button:hover{text-decoration:none;}
.button:active{position:relative;top:1px;}
.white{
color:#606060;
border:solid 1px #b7b7b7;
background:#fff;
background:-webkit-gradient(linear, left top, left bottom, from(#fff), to(#ededed));
background:-moz-linear-gradient(top, #fff, #ededed);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#ededed');
}
.white:hover{
background:#ededed;
background:-webkit-gradient(linear, left top, left bottom, from(#fff), to(#dcdcdc));
background:-moz-linear-gradient(top, #fff, #dcdcdc);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dcdcdc');
}
.white:active{
color:#999;
background:-webkit-gradient(linear, left top, left bottom, from(#ededed), to(#fff));
background:-moz-linear-gradient(top, #ededed, #fff);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#ffffff');
}