最终日历控件实例代码地址:http://www.oschina.net/code/snippet_2352644_55198
什么是日历控件?效果什么样子?这是一个网站上的在线演示效果:http://www.jq22.com/yanshi5303
我们开发的最终实现就是大致这个样子,我们简单把效果的逻辑简单概述:
一个input
我们点击input会弹出日历控件
我们点击日历控件的日期就会显示到input中
日历控件的年月可更改选择
可以清除input的日期
我们这样就简单的概述了这个效果,下面我们就会出现下面的疑问?
在js中,时期是怎么获取和设置!
这次的实例开发讲解,会分为2篇,日历控件实例相对来说要先有准备知识的了解,我们在以前的博客中只有在cookie中简单介绍过date对象的gmt转化方法。
一.date对象基本知识
1.date对象创建
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>date</title> <style type="text/css"> </style> </head> <body> <input type="text" id="date" value="日历控件"/> </body> <script type="text/javascript"> var dateObj = new Date(); alert(typeof dateObj); </script> </html>
通过Date类我们直接可创建date对象,在创建对象,不设置参数的情况下,默认的date对象使用当前时间做参数。
比如今天是2016/4/5那么日期对象的年 月 日分别就是2016 4 5。
2.date对象读取
读取就是拿,拿到日期对象中我们想要的具体内容,比如:年,月,日,时分秒,等等等。
我们获取年月日:
var dateObj = new Date(); alert("年:"+dateObj.getFullYear()); alert("月:"+dateObj.getMonth()); alert("日:"+dateObj.getDate());
日期对象月是返回0-11,所以我们拿到的值+1才是真实月份。
获取周:
var dateObj = new Date(); alert("周:"+dateObj.getDay());
周的特殊之处就是星期日的处理,返回是0。
获取时分秒:
var dateObj = new Date(); alert("时:"+dateObj.getHours()); alert("分:"+dateObj.getMinutes()); alert("秒:"+dateObj.getSeconds());
这里的返回值都是从0开始,0其实就是对应代表了24小时,60分钟,60秒,和周类似。
获取毫秒:
更加精确的时间,不在很特殊时我们也不会拿去的,和秒的关系 1秒=1000毫秒
var dateObj = new Date(); alert("毫秒:"+dateObj.getMilliseconds());
同理,返回0代表1000毫秒值。
返回 1970 年 1 月 1 日至今的毫秒数:
这个就是unix时间戳的使用了,我们会拿到距离时间:
var dateObj = new Date(); alert("距离 1970 年 1 月 1 日的毫秒数:"+dateObj.getTime());
我们采用默认参数,date对象就是当前时间,获取就是这个时间距离1970/1/1的毫秒数。
转为GMTString时间:
这个就是我们cookie过期时间的使用了:
var dateObj = new Date(); alert("GMTString:"+dateObj.toUTCString());
这其实是一种日期格式,cookie你必须用这种格式,我们使用的方法是现在推荐的,toGMTString()不被推荐使用。
其实除了这些,还有根据世界时间的返回,我们这里就不在介绍了。
3.date对象设置
几乎所有的获取操作,都会对应设置操作,我们创建了date对象,对象包含各种日期信息(年,月,日等),这些信息其实都是来自new时的参数,我们默认采用当前。
我们还能修改对象中的各种信息,修改了我们在获取,就是拿到修改的信息了。
我们设置年月日:
var dateObj = new Date(); alert("默认年:"+dateObj.getFullYear()); alert("默认月:"+dateObj.getMonth()); alert("默认日:"+dateObj.getDate()); dateObj.setFullYear(2008); dateObj.setMonth(8); dateObj.setDate(8); alert("修改后年:"+dateObj.getFullYear()); alert("修改后月:"+dateObj.getMonth()); alert("修改后日:"+dateObj.getDate());
我们先获取默认参数的时间,然后设置指定的年月日,获取时就知道确实修改了对应信息。
其他的时分秒类似不做介绍。
根据距离 1970 年 1 月 1 日至今的毫秒数设置日期对象:
与gettime正好相反的操作,get是拿到毫秒,set是根据毫秒设置修改date的所有信息。
var dateObj = new Date(); alert("默认年:"+dateObj.getFullYear()); alert("默认月:"+dateObj.getMonth()); alert("默认日:"+dateObj.getDate()); var now=dateObj.getTime();//获取1970毫秒 var prev=now-24*60*60*1000;//获取昨天距离1970的毫秒,减去一天的毫秒数,一天是24小时,1小时60分钟,1分钟60秒,1秒是1000毫秒 dateObj.setTime(prev); alert("修改后年:"+dateObj.getFullYear()); alert("修改后月:"+dateObj.getMonth()); alert("修改后日:"+dateObj.getDate());
二.date对象小实例
仅仅知道了date的创建,设置和获取是不足以让我们灵活运用它,我们下面通过开发多个小实例,加强我们对date的使用和了解。
实例1:页面今日日期显示
在一些网站,我们会看到显示今天的年月日和星期几信息,我们怎么把这些信息显示到页面当中?
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>date</title> <style type="text/css"> </style> </head> <body> <input type="text" id="date" value="日历控件"/> <div id="show"></div> </body> <script type="text/javascript"> var show=document.getElementById("show"); var dateObj = new Date(); var year=dateObj.getFullYear(); var month=dateObj.getMonth();//0是12月 var day=dateObj.getDate(); var week=dateObj.getDay();//0是星期日 show.innerHTML="当前日期"+year+"年"+month+"月"+day+"日"+"星期"+week; </script> </html>
通过截图,我们看到的已知问题就是月份,月份是要+1的,因为返回值是0-11代表1-12月,一个隐藏问题就是星期,如果是星期日,返回是0;对于转化映射的处理,我们可以采用js的switch case语句。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>date</title> <style type="text/css"> </style> </head> <body> <input type="text" id="date" value="日历控件"/> <div id="show"></div> </body> <script type="text/javascript"> var show=document.getElementById("show"); var dateObj = new Date(); var year=dateObj.getFullYear(); var month=toyear(dateObj.getMonth());//0是12月 var day=dateObj.getDate(); var week=toweek(dateObj.getDay());//0是星期日 show.innerHTML="当前日期"+year+"年"+month+"月"+day+"日"+week; function toweek(week){ switch(week) { case 0: return "星期日"; break; case 1: return "星期一"; break; case 2: return "星期二"; break; case 3: return "星期三"; break; case 4: return "星期四"; break; case 5: return "星期五"; break; case 6: return "星期六"; break; default: }; }; function toyear(month){ switch(month) { case 0: return "1"; break; case 1: return "2"; break; case 2: return "3"; break; case 3: return "4"; break; case 4: return "5"; break; case 5: return "6"; break; case 6: return "7"; break; case 7: return "8"; break; case 8: return "9"; break; case 9: return "10"; break; case 10: return "11"; break; case 11: return "12"; break; default: }; }; </script> </html>
截图:
达到我们想要的结果。
实例2:简单时钟
一个时钟,就会包含时分秒这些信息,并且会动态变化,我们利用经常使用的setinterval函数,并且把间隔设置为1000也就是1秒就正好满足动态变化的需求:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>date</title> <style type="text/css"> </style> </head> <body> <input type="text" id="date" value="日历控件"/> <div id="show"></div> </body> <script type="text/javascript"> var show=document.getElementById("show"); var dateObj = new Date(); var hour=tohour(dateObj.getHours()); var minu=tominu(dateObj.getMinutes()); var sec=tosec(dateObj.getSeconds()); show.innerHTML=hour+"时"+minu+"分"+sec+"秒"; setInterval(function(){ dateObj = new Date(); hour=tohour(dateObj.getHours()); minu=tominu(dateObj.getMinutes()); sec=tosec(dateObj.getSeconds()); show.innerHTML=hour+"时"+minu+"分"+sec+"秒"; },1000); function tohour(t){ if(t==0){ return 24; }else{ return t; }; }; function tominu(t){ if(t==0){ return 60; }else{ return t; }; }; function tosec(t){ if(t==0){ return 60; }else{ return t; }; }; </script> </html>
三.本月日历
1.静态结构创建
今天是2016年4月5日,我们想要把4月的所有信息显示出来,并且把5日特殊标记,大概样子是这样的:
最上面的月和年是比较简单的,我们直接获取就可以了,下面的内容就比较麻烦了,我们分析发现,
1.本月的信息会全部显示,
2.而且1号这一天根据它所在的周,要在前面出现留空位置,
3.5这个就是当前日,加入特殊标记。
我们先不考虑动态处理问题,我们先把静态结构完成,用写死的形式把这个效果写出来:
效果截图:
代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>date</title> <style type="text/css"> #box{width:350px;} #title{width:350px; height:50px;} #month{ float:left;width:60px; height:50px;text-align:center;cursor:pointer;line-height:50px;} #year{float:left;width:80px; height:50px;text-align:center;cursor:pointer;line-height:50px;} #week{ width:350px;height:50px;} #week div{ float:left; width:48px; height:48px; margin:1px; background:#C90; color:#fff; text-align:center; line-height:48px; cursor:pointer;} #con{ width:350px;} #con div{ float:left; width:48px; height:48px; margin:1px; background:#999; color:#333; text-align:center; line-height:48px; cursor:pointer;} #con div.now{background:#09F; color:#fff;} </style> </head> <body> <div id="box"> <div id="title"> <div id="month"></div> <div id="year"></div> </div> <div id="week"> <div>日</div> <div>一</div> <div>二</div> <div>三</div> <div>四</div> <div>五</div> <div>六</div> </div> <div id="con"> <div></div> <div></div> <div></div> <div></div> <div></div> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div class="now">5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> <div>10</div> <div>11</div> <div>12</div> <div>13</div> <div>14</div> <div>15</div> <div>16</div> <div>17</div> <div>18</div> <div>19</div> <div>20</div> <div>21</div> <div>22</div> <div>23</div> <div>24</div> <div>25</div> <div>26</div> <div>27</div> <div>28</div> <div>29</div> <div>30</div> </div> </div> </body> <script type="text/javascript"> window.onload=function(){ var omonth=document.getElementById("month"); var oyear=document.getElementById("year"); var dateObj = new Date(); var year=dateObj.getFullYear(); var month=toyear(dateObj.getMonth());//0是12月 omonth.innerHTML=month+"月"; oyear.innerHTML=year+"年"; function toyear(month){ switch(month) { case 0: return "1"; break; case 1: return "2"; break; case 2: return "3"; break; case 3: return "4"; break; case 4: return "5"; break; case 5: return "6"; break; case 6: return "7"; break; case 7: return "8"; break; case 8: return "9"; break; case 9: return "10"; break; case 10: return "11"; break; case 11: return "12"; break; default: }; }; }; </script> </html>
2.动态处理日期
我们把日的显示写死,我们只要利用动态处理,就可以完成动态创建了,我们要想完成留空的处理,我们要获取的信息包含如下:
1.本月1日是星期几?如果是星期5,也就是返回了5,那么留空就是5,是星级1,返回1留空就是1
2.获取这个月日的总个数,这个简单1 3 5 7 8 10 12哈哈,31天永不差,需注意闰年,用作循环创建所有的日
3.返回今日,比如这个例子返回5,再循环中我们要判断等于5的加入特殊处理
如何获取本月1日信息?
我们只要先创建一个默认的日期对象,然后利用setdate(1)把对象的日设置为1其实就获取了本月1号的信息,然后然获取所在的周,就首先拿到了留空个数:
//获取本月1号的周值 var oneyear = new Date(); oneyear.setDate(1); var oneweek=oneyear.getDay(); alert(oneweek)
非常的完美,下面我们实现2,也就是拿到本月总的日数,基本规律就是口诀,不过我们先判断一把是否是闰年,要遇到2月特殊处理:
判断闰年条件①:非整百年数除以4,无余为闰,有余为平;②整百年数除以400,无余为闰有余平。
//闰年判断函数 function isLeapYear(year) { if( (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)){ return true; }else{ return false; }; };
我们测试输出总日数:
//本月总日数 var alld=alldays(year,dateObj.getMonth()); alert(alld); //获取本月总日数方法 function alldays(year,month){ if(isLeapYear(year)){//闰年 switch(month) { case 0: return "31"; break; case 1: return "29"; break; //2月 case 2: return "31"; break; case 3: return "30"; break; case 4: return "31"; break; case 5: return "30"; break; case 6: return "31"; break; case 7: return "31"; break; case 8: return "30"; break; case 9: return "31"; break; case 10: return "30"; break; case 11: return "31"; break; default: }; }else{//平年 switch(month) { case 0: return "31"; break; case 1: return "28"; break; //2月 case 2: return "31"; break; case 3: return "30"; break; case 4: return "31"; break; case 5: return "30"; break; case 6: return "31"; break; case 7: return "31"; break; case 8: return "30"; break; case 9: return "31"; break; case 10: return "30"; break; case 11: return "31"; break; default: }; }; }; //闰年判断函数 function isLeapYear(year){ if( (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)){ return true; }else{ return false; }; };
最后一个重要信息,当前日:
//当前是几 var nowd=dateObj.getDate(); alert(nowd);
准备工作完成,我们初始化显示我们的时间:
//初始化显示本月信息 init(oneweek,alld,nowd); //初始化日期显示方法 function init(oneweek,alld,nowd){ for(var i=1;i<=oneweek;i++){//留空 var eday=document.createElement("div"); eday.innerHTML=""; con.appendChild(eday); }; for(var i=1;i<=alld;i++){//正常区域 var eday=document.createElement("div"); if(i==nowd){ eday.innerHTML=i; eday.className="now"; con.appendChild(eday); }else{ eday.innerHTML=i; con.appendChild(eday); }; }; };
我们把所有代码整理,看到下面截图效果:
效果没有变,不过内容是通过js添加:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>date</title> <style type="text/css"> #box{width:350px;} #title{width:350px; height:50px;} #month{ float:left;width:60px; height:50px;text-align:center;cursor:pointer;line-height:50px;} #year{float:left;width:80px; height:50px;text-align:center;cursor:pointer;line-height:50px;} #week{ width:350px;height:50px;} #week div{ float:left; width:48px; height:48px; margin:1px; background:#C90; color:#fff; text-align:center; line-height:48px; cursor:pointer;} #con{ width:350px;} #con div{ float:left; width:48px; height:48px; margin:1px; background:#999; color:#333; text-align:center; line-height:48px; cursor:pointer;} #con div.now{background:#09F; color:#fff;} </style> </head> <body> <div id="box"> <div id="title"> <div id="month"></div> <div id="year"></div> </div> <div id="week"> <div>日</div> <div>一</div> <div>二</div> <div>三</div> <div>四</div> <div>五</div> <div>六</div> </div> <div id="con"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //月年的显示 var omonth=document.getElementById("month"); var oyear=document.getElementById("year"); var con=document.getElementById("con"); var dateObj = new Date(); var year=dateObj.getFullYear(); var month=toyear(dateObj.getMonth());//0是12月 omonth.innerHTML=month+"月"; oyear.innerHTML=year+"年"; //获取本月1号的周值 var oneyear = new Date(); oneyear.setDate(1); var oneweek=oneyear.getDay(); //本月总日数 var alld=alldays(year,dateObj.getMonth()); //当前是几 var nowd=dateObj.getDate(); //初始化显示本月信息 init(oneweek,alld,nowd); //初始化日期显示方法 function init(oneweek,alld,nowd){ for(var i=1;i<=oneweek;i++){//留空 var eday=document.createElement("div"); eday.innerHTML=""; con.appendChild(eday); }; for(var i=1;i<=alld;i++){//正常区域 var eday=document.createElement("div"); if(i==nowd){ eday.innerHTML=i; eday.className="now"; con.appendChild(eday); }else{ eday.innerHTML=i; con.appendChild(eday); }; }; }; //获取本月总日数方法 function alldays(year,month){ if(isLeapYear(year)){//闰年 switch(month) { case 0: return "31"; break; case 1: return "29"; break; //2月 case 2: return "31"; break; case 3: return "30"; break; case 4: return "31"; break; case 5: return "30"; break; case 6: return "31"; break; case 7: return "31"; break; case 8: return "30"; break; case 9: return "31"; break; case 10: return "30"; break; case 11: return "31"; break; default: }; }else{//平年 switch(month) { case 0: return "31"; break; case 1: return "28"; break; //2月 case 2: return "31"; break; case 3: return "30"; break; case 4: return "31"; break; case 5: return "30"; break; case 6: return "31"; break; case 7: return "31"; break; case 8: return "30"; break; case 9: return "31"; break; case 10: return "30"; break; case 11: return "31"; break; default: }; }; }; //闰年判断函数 function isLeapYear(year){ if( (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)){ return true; }else{ return false; }; }; //月份转化方法 function toyear(month){ switch(month) { case 0: return "1"; break; case 1: return "2"; break; case 2: return "3"; break; case 3: return "4"; break; case 4: return "5"; break; case 5: return "6"; break; case 6: return "7"; break; case 7: return "8"; break; case 8: return "9"; break; case 9: return "10"; break; case 10: return "11"; break; case 11: return "12"; break; default: }; }; }; </script> </html>
四.动态日历
什么是动态,就是可以利用上一页或者下一页查看上一个月,下一个月,上上一个月的日历信息!
我们把自己程序进一步优化,让更多的获取来自函数:
经过一顿的修正,我们把近乎所有获取操作都通过new的date实现:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>date</title> <style type="text/css"> #box{width:350px;} #title{width:350px; height:50px;} #month{ float:left;width:60px; height:50px;text-align:center;cursor:pointer;line-height:50px;} #year{float:left;width:80px; height:50px;text-align:center;cursor:pointer;line-height:50px;} #week{ width:350px;height:50px;} #week div{ float:left; width:48px; height:48px; margin:1px; background:#C90; color:#fff; text-align:center; line-height:48px; cursor:pointer;} #con{ width:350px;} #con div{ float:left; width:48px; height:48px; margin:1px; background:#999; color:#333; text-align:center; line-height:48px; cursor:pointer;} #con div.now{background:#09F; color:#fff;} </style> </head> <body> <div id="box"> <div id="title"> <div id="month"></div> <div id="year"></div> </div> <div id="week"> <div>日</div> <div>一</div> <div>二</div> <div>三</div> <div>四</div> <div>五</div> <div>六</div> </div> <div id="con"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //===================get ele=============================== var omonth=document.getElementById("month"); var oyear=document.getElementById("year"); var con=document.getElementById("con"); //===================set year month=============================== //默认时间对象 var dateObj = new Date(); var year=dateObj.getFullYear(); var month=toyear(dateObj);//0是12月 //月年的显示 omonth.innerHTML=month+"月"; oyear.innerHTML=year+"年"; //===================set day=============================== //获取本月1号的周值 var oneweek=oneyearoneday(dateObj); //本月总日数 var alld=alldays(dateObj); //当前是几 var nowd=nowday(dateObj); //初始化显示本月信息 init(oneweek,alld,nowd); //===================function=============================== //初始化日期显示方法 function init(oneweek,alld,nowd){ for(var i=1;i<=oneweek;i++){//留空 var eday=document.createElement("div"); eday.innerHTML=""; con.appendChild(eday); }; for(var i=1;i<=alld;i++){//正常区域 var eday=document.createElement("div"); if(i==nowd){ eday.innerHTML=i; eday.className="now"; con.appendChild(eday); }else{ eday.innerHTML=i; con.appendChild(eday); }; }; }; //获取本月1号的周值 function oneyearoneday(dateObj){ var oneyear = new Date(); var year=dateObj.getFullYear(); var month=dateObj.getMonth();//0是12月 oneyear.setFullYear(year); oneyear.setMonth(month);//0是12月 oneyear.setDate(1); return oneyear.getDay(); }; //当前是几 function nowday(dateObj){ return dateObj.getDate(); }; //获取本月总日数方法 function alldays(dateObj){ var year=dateObj.getFullYear(); var month=dateObj.getMonth(); if(isLeapYear(year)){//闰年 switch(month) { case 0: return "31"; break; case 1: return "29"; break; //2月 case 2: return "31"; break; case 3: return "30"; break; case 4: return "31"; break; case 5: return "30"; break; case 6: return "31"; break; case 7: return "31"; break; case 8: return "30"; break; case 9: return "31"; break; case 10: return "30"; break; case 11: return "31"; break; default: }; }else{//平年 switch(month) { case 0: return "31"; break; case 1: return "28"; break; //2月 case 2: return "31"; break; case 3: return "30"; break; case 4: return "31"; break; case 5: return "30"; break; case 6: return "31"; break; case 7: return "31"; break; case 8: return "30"; break; case 9: return "31"; break; case 10: return "30"; break; case 11: return "31"; break; default: }; }; }; //闰年判断函数 function isLeapYear(year){ if( (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)){ return true; }else{ return false; }; }; //月份转化方法 function toyear(dateObj){ var month=dateObj.getMonth() switch(month) { case 0: return "1"; break; case 1: return "2"; break; case 2: return "3"; break; case 3: return "4"; break; case 4: return "5"; break; case 5: return "6"; break; case 6: return "7"; break; case 7: return "8"; break; case 8: return "9"; break; case 9: return "10"; break; case 10: return "11"; break; case 11: return "12"; break; default: }; }; }; </script> </html>
我们如何检验结果的活跃性呢?我们只要把new date的月份做一次修改,就可以检测结果了:
设置为上一个月,看结果:
有些完美了是不是,我们试想如果这中设置方式结合页面处理,是不是就成就了我们的实现,到这里上篇结束。