javascript blog式日历控件
近来要做一个记事本系统,想找一个合适的日历控件,但网上的都是那种日历选择控件。
于是到qq的记事本系统找了一个,但里面的算法有点落后,所以用了它的样式自己写了个。
效果:
>
年 月
日
一
二
三
四
五
六
程序说明
【date】
这个日历控件运用了很多date相关操作和方法。
先说说date对象几个有用的属性:
getfullyear:返回年份值
getmonth:返回月份值
getdate:返回一个月中的日期值
getday:返回一周中的日期值
其中对getday可能比较陌生,下面列出值对应的星期:
值 星期
0 星期天
1 星期一
2 星期二
3 星期三
4 星期四
5 星期五
6 星期六
这几个属性都是根据本地时间获取的,还有getutcfullyear、getutcmonth、getutcdate、getutcday这几个属性是全球标准时间对应的值。
下面说说获取日期对象,获取当前日期很简单:
new date()
获取指定日期:
new date(this.options.selectday)
获取指定年月日的日期:
new date(this.year, this.month - 1, d)
下面是几个比较有技巧的地方:
首先,做日历控件时需要知道该月第一天离星期天的天数,参照getday对应值,发现这刚好等于该月第一天的getday值,所以可以这样获得:
new date(this.year, this.month - 1, 1).getday()
还有是获取该月的天数,这里比较精妙,通过获取该月最后一天的getdate值就可以得到该月的天数,但没有办法直接获取该月最后一天。
这里有一个方法,当获取指定年月日的日期时,设置日参数为0,就可以获取上一个月的最后一天,所以可以这样获取:
new date(this.year, this.month, 0).getdate()
这个方法是很久以前在别人代码中发现的。
使用说明:
首先是实例化一个calendar,并设置参数。
参数说明:
year:要显示的年份
month:要显示的月份
selectday:选择日期
onselectday:在选择日期触发
ontoday:在当天日期触发
onfinish:日历画完后触发
一般selectday设置成选择了的日期,并在onselectday中设置一个函数用来设置这个日期的样式,
例如实例里selectday设置成今个月10号并在那天样式设为onselect:
selectday: new date().setdate(10),
onselectday: function(o){ o.classname = "onselect"; },
而ontoday就用来设置今日日期的样式,
例如实例里面把今天的日期的样式设为ontoday:
ontoday: function(o){ o.classname = "ontoday"; },
在onfinish中可以放需要设置日历的程序。
可以通过this.year和this.month获取当前日历显示的年份和月份。
对有数据的日期的也在这里设置,例如实例中是有一个当前月份的有数据的日期列表,然后根据这个列表对相应的日期进行设置:
code
var flag = [10,15,20];
for(var i = 0, len = flag.length; ilen; i++){
this.days[flag[i]].innerhtml = ""alert('日期是:"+this.year+"/"+this.month+"/"+flag[i]+"');return false;\">" + flag[i] + "";
}
实例中是固定了这个日期列表,实际应用中可以根据年份月份获取对应的日期列表,
个人推荐用年份月份通过ajax获取。
程序还有下面这几个方法:
nowmonth:显示当前月
premonth:显示上一月
nextmonth:显示下一月
preyear:显示上一年
nextyear:显示下一年
predraw:根据日期参数画日历
程序代码:
code
var $ = function (id) {
return "string" == typeof id ? document.getelementbyid(id) : id;
};
var class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
var extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
var calendar = class.create();
calendar.prototype = {
initialize: function(container, options) {
this.container = $(container);//容器(table结构)
this.days = [];//日期对象列表
this.setoptions(options);
this.year = this.options.year || new date().getfullyear();
this.month = this.options.month || new date().getmonth() + 1;
this.selectday = this.options.selectday ? new date(this.options.selectday) : null;
this.onselectday = this.options.onselectday;
this.ontoday = this.options.ontoday;
this.onfinish = this.options.onfinish;
this.draw();
},
//设置默认属性
setoptions: function(options) {
this.options = {//默认值
year:0,//显示年
month:0,//显示月
selectday:null,//选择日期
onselectday:function(){},//在选择日期触发
ontoday:function(){},//在当天日期触发
onfinish:function(){}//日历画完后触发
};
extend(this.options, options || {});
},
//当前月
nowmonth: function() {
this.predraw(new date());
},
//上一月
premonth: function() {
this.predraw(new date(this.year, this.month - 2, 1));
},
//下一月
nextmonth: function() {
this.predraw(new date(this.year, this.month, 1));
},
//上一年
preyear: function() {
this.predraw(new date(this.year - 1, this.month - 1, 1));
},
//下一年
nextyear: function() {
this.predraw(new date(this.year + 1, this.month - 1, 1));
},
//根据日期画日历
predraw: function(date) {
//再设置属性
this.year = date.getfullyear(); this.month = date.getmonth() + 1;
//重新画日历
this.draw();
},
//画日历
draw: function() {
//用来保存日期列表
var arr = [];
//用当月第一天在一周中的日期值作为当月离第一天的天数
for(var i = 1, firstday = new date(this.year, this.month - 1, 1).getday(); ifirstday; i++){ arr.push(0); }
//用当月最后一天在一个月中的日期值作为当月的天数
for(var i = 1, monthday = new date(this.year, this.month, 0).getdate(); imonthday; i++){ arr.push(i); }
//清空原来的日期对象列表
this.days = [];
//插入日期
var frag = document.createdocumentfragment();
while(arr.length){
//每个星期插入一个tr
var row = document.createelement("tr");
//每个星期有7天
for(var i = 1; i7; i++){
var cell = document.createelement("td"); cell.innerhtml = " ";
if(arr.length){
var d = arr.shift();
if(d){
cell.innerhtml = d;
this.days[d] = cell;
var on = new date(this.year, this.month - 1, d);
//判断是否今日
this.issame(on, new date()) && this.ontoday(cell);
//判断是否选择日期
this.selectday && this.issame(on, this.selectday) && this.onselectday(cell);
}
}
row.appendchild(cell);
}
frag.appendchild(row);
}
//先清空内容再插入(ie的table不能用innerhtml)
while(this.container.haschildnodes()){ this.container.removechild(this.container.firstchild); }
this.container.appendchild(frag);
//附加程序
this.onfinish();
},
//判断是否同一日
issame: function(d1, d2) {
return (d1.getfullyear() == d2.getfullyear() && d1.getmonth() == d2.getmonth() && d1.getdate() == d2.getdate());
}
}
测试代码:
code
var cale = new calendar("idcalendar", {
selectday: new date().setdate(10),
onselectday: function(o){ o.classname = "onselect"; },
ontoday: function(o){ o.classname = "ontoday"; },
onfinish: function(){
$("idcalendaryear").innerhtml = this.year; $("idcalendarmonth").innerhtml = this.month;
var flag = [10,15,20];
for(var i = 0, len = flag.length; ilen; i++){
this.days[flag[i]].innerhtml = ""alert('日期是:"+this.year+"/"+this.month+"/"+flag[i]+"');return false;\">" + flag[i] + "";
}
}
});
$("idcalendarpre").onclick = function(){ cale.premonth(); }
$("idcalendarnext").onclick = function(){ cale.nextmonth(); }
$("idcalendarpreyear").onclick = function(){ cale.preyear(); }
$("idcalendarnextyear").onclick = function(){ cale.nextyear(); }
$("idcalendarnow").onclick = function(){ cale.nowmonth(); }
转载请注明出处:http://www.cnblogs.com/cloudgamer/
如有任何建议或疑问,欢迎留言讨论。
如果觉得文章不错的话,欢迎点一下右下角的推荐。
程序中包含的js工具库cjl.0.1.min.js,原文在这里。
标签: javascript, date, 日历, blog
绿色通道:好文要顶关注我收藏该文与我联系
posted @ 2008-08-23 00:25 cloudgamer 阅读(30189) 评论(75)编辑 收藏
发表评论
2273673
回复 引用 查看
#1楼 2008-08-23 02:31 clefoo
兼容不
回复 引用 查看
#2楼 2008-08-23 05:24 飞天小肥猪(膘叔)
能弹出不?
回复 引用 查看
#3楼[楼主] 2008-08-23 08:20 cloudgamer
@clefoo
兼容的
@飞天小肥猪(膘叔)
弹出的那种网上有很多了我做的不是那种
回复 引用 查看
#4楼 2008-08-27 15:46 陛下
兄弟看上去精于js啊,多指点!
回复 引用 查看
#5楼[楼主] 2008-08-27 17:26 cloudgamer
@陛下
共同学习
回复 引用
#6楼 2008-09-01 10:25 joyce004[未注册用户]
var $ = function (id) {
return "string" == typeof id ? document.getelementbyid(id) : id;
};
var class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
请问下这几段代码是什么意思,看的懂,不过不是很明白这样做的好处,可以解释一下吗?
回复 引用 查看
#7楼[楼主] 2008-09-01 13:55 cloudgamer
@joyce004
你可以看看initialize和setoptions的使用
回复 引用 查看
#8楼 2008-09-02 11:23 杨阳
代码质量相当搞
回复 引用 查看
#9楼[楼主] 2008-09-02 20:10 cloudgamer
@杨阳
谢谢支持
回复 引用
#10楼 2008-10-18 21:28 xukongqiang[未注册用户]
太强了,很精炼
回复 引用 查看
#11楼[楼主] 2008-10-19 13:14 cloudgamer
@xukongqiang
谢谢
回复 引用 查看
#12楼 2008-10-23 14:03 selfocus
兄台确实精于js的高手,多交流哦!
回复 引用 查看
#13楼[楼主] 2008-10-23 19:57 cloudgamer
@selfocus
呵呵
多多交流
回复 引用
#14楼 2008-11-06 10:49 ""kkking[未注册用户]
选 择 时 最 好 屏 幕 别 闪 ,还 有 有 无 带 农 历 的 ?谢 谢
回复 引用 查看
#15楼[楼主] 2008-11-06 16:11 cloudgamer
@""kkking
屏幕闪是什么意思?我这里好像没有闪哦
农历有空的话试试加进去
回复 引用
#16楼 2008-11-10 09:42 112233[未注册用户]
为什么10号,15号,20号是红字的
回复 引用 查看
#17楼[楼主] 2008-11-10 10:13 cloudgamer
@112233
对有数据的日期的也在这里设置,例如实例中是有一个当前月份的有数据的日期列表,然后根据这个列表对相应的日期进行设置:
var flag = [10,15,20];
for(var i = 0, len = flag.length; i
回复 引用
#18楼 2009-01-15 22:32 liminz[未注册用户]
你好,我想请教有个现有的日历里的默认字体的颜色无法更改,请求楼主的帮忙.
我就发给你的邮箱吧,这里也不能挂附件.
回复 引用
#19楼 2009-02-17 14:29 mymickey[未注册用户]
想问问 getutcfullyear 和getfullyear的区别 我试了试都一样的呢
回复 引用 查看
#20楼[楼主] 2009-02-18 09:30 cloudgamer
@mymickey
utc就是协调世界时
具体去baidu一下吧
我也不太懂
回复 引用
#21楼 2009-02-23 04:16 soso0704
你好,我很想一个html源码的日历放在我网页上,但我找了很久都是不行的,自己又不会弄,你可以发这个给我吗?邮箱:soso840704@163.com。
回复 引用 查看
#22楼[楼主] 2009-02-23 08:21 cloudgamer
@soso0704
不是有完整实例下载了吗
http://files.cnblogs.com/cloudgamer/blogcalendar.rar
回复 引用
#23楼 2009-02-23 13:23 我爱你
lz怎样把10号,15号,20号的特殊处理改为全部日期,并且日期添加处理是链接matter.html
回复 引用 查看
#24楼[楼主] 2009-02-23 15:49 cloudgamer
@我爱你
你可以参考测试代码中onfinish是怎么写的
然后修改一下就可以了
回复 引用
#25楼 2009-02-23 19:19 我爱你
难道要把10.15.20改为1.2.3.....31吗?
回复 引用 查看
#26楼[楼主] 2009-02-24 08:25 cloudgamer
@我爱你
那个for循环改成1到31不就行了嘛
回复 引用
#27楼 2009-02-26 14:20 deandean[未注册用户]
回楼主,我把for循环改成1到31后发现一个问题,如果当前月有31天,那么可以选择下一月或者下一年,如果当前月只有28天,比如说2月,那么就无法选择下一月或者下一年了。
回复 引用 查看
#28楼[楼主] 2009-02-26 14:25 cloudgamer
@deandean
你可以把monthday 作为onfinish的参数传递过去
就可以在函数中获取有多少天了
回复 引用
#29楼 2009-03-17 17:12 新猪猪[未注册用户]
呵呵,最好是那种,绑定到一个文本框onfocus就直接出来,比如my97datepicker那种,当然最好是带上时间的选择,比如后台要做统计,需要2个日期选择(当然包含时间最好),我也正在写,日期写完了,再加时间,当时相信楼主的js一定比我的好,呵呵。。。希望可以向你多学习学习。。。
回复 引用 查看
#30楼[楼主] 2009-03-17 17:18 cloudgamer
@新猪猪
其实原理都是那样的了
而且我自己也是用my97datepicker就不需要自己写一个了
相信你写的也不错,加油
回复 引用
#31楼 2009-03-25 13:39 swd[未注册用户]
判断这个月份有几天在哪定义的
回复 引用 查看
#32楼[楼主] 2009-03-25 13:51 cloudgamer
@swd
上面不是说了嚒
new date(this.year, this.month, 0).getdate()
回复 引用
#33楼 2009-04-14 17:12 sdj[未注册用户]
你好!看了你的许多代码,都有一个共同的不明白之处就是:
extend(this.options, options || {});
extend方法的第二个参数是什么意思呢
回复 引用 查看
#34楼[楼主] 2009-04-14 17:28 cloudgamer
@sdj
options 是函数的参数
回复 引用
#35楼 2009-04-15 09:35 sdj[未注册用户]
楼主好啊,
extend(this.options, options || {});
extend方法的第二个参数是什么意思呢,
我指的是 "options || {}",这个得到的是什么结果,谢谢楼主
回复 引用 查看
#36楼[楼主] 2009-04-15 10:20 cloudgamer
@sdj
如果options 这个参数有的话就用options 如果没有的话就用{}
||的这个用法可以参考这里
https://developer.mozilla.org/en/core_javascript_1.5_guide/operators/logical_operators
回复 引用 查看
#37楼 2009-06-26 14:16 louis.lu.sz
讲解的非常非常的详细。
赞!
回复 引用 查看
#38楼 2009-08-25 16:23 wtcsy
顶
对比了一下cloudgamer和果果的日历,
还是喜欢cloudgamer的写法,
虽然果果的那个上面有很多值得学习的地方...........
回复 引用 查看
#39楼[楼主] 2009-08-25 17:52 cloudgamer
@wtcsy
@louis.lu.sz
谢谢支持
回复 引用
#40楼 2009-08-31 18:40 jtootl[未注册用户]
博主真强!顶你!楼主是巨人,我用了博主的代码,所以我是站在巨人的肩膀上了,哈哈。
不过要是能多提供几种样式就更好了,呵呵。
对了 日历的大小能变动吗?
回复 引用 查看
#41楼[楼主] 2009-08-31 22:35 cloudgamer
@jtootl
样式其实都可以自己设的
我关键还是在js的部分
回复 引用
#42楼 2009-09-03 14:17 jtootl[未注册用户]
再请问下博主,我能把月份做成链接吗?
>
“9月”那里,
我想的是如果想看9月的博文,就点“9月”的链接。
回复 引用 查看
#43楼[楼主] 2009-09-03 15:32 cloudgamer
@jtootl
可以啊
$("idcalendaryear").innerhtml = this.year; $("idcalendarmonth").innerhtml = this.month;
这部分拟改成一个连接就行啦
回复 引用
#44楼 2009-10-08 11:18 goodluckxw[未注册用户]
您好 请问一下这个控件 点击日期为什么点不了呢 如果想点击某个日期 焦点还要落在点击的日期上 怎么处理?
回复 引用 查看
#45楼[楼主] 2009-10-08 16:29 cloudgamer
@goodluckxw
你可以参考
for(var i = 1, len = this.days.length; i
回复 引用
#46楼 2009-10-28 16:44 lengwei[未注册用户]
var class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
var extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
楼主 这两段不怎么理解啊!
回复 引用 查看
#47楼[楼主] 2009-10-28 17:03 cloudgamer
@lengwei
可以看看apply的用法
后面那个是扩展对象
回复 引用 查看
#48楼 2009-10-30 10:37 流风--回雪
var class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
var extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
楼主 你这段内容是不是借鉴prototype.js的源码?好熟悉啊。。呵呵
回复 引用 查看
#49楼[楼主] 2009-10-30 10:49 cloudgamer
@流风--回雪
是啊,就是抄它的
呵呵
回复 引用 查看
#50楼 2009-11-02 15:18 chinarenkai
我比较认真的看完了。也做了一个小demo,跟数据库绑定,设计的不错,注释非常perfect,佩服!哈哈
回复 引用
#51楼 2009-11-10 14:35 gorden[未注册用户]
能支持中国日历就完美了
回复 引用 查看
#52楼[楼主] 2009-11-10 17:17 cloudgamer
@gorden
下次修改的话可以考虑
@chinarenkai
谢谢支持
回复 引用
#53楼 2009-11-11 18:33 mindycooky[未注册用户]
cloudgamer:
我想问一下啊,我js不好的:(
如何根据已有日期初始化日历呢?比如我点上个月,带日期参数重新调入页面,这个时候,我在哪里设置日历的年、月,并根据这个年月重新画呢?
回复 引用 查看
#54楼[楼主] 2009-11-11 20:31 cloudgamer
@mindycooky
设置这两个属性
year:要显示的年份
month:要显示的月份
回复 引用
#55楼 2009-11-12 20:25 mindycooky[未注册用户]
引用cloudgamer:
@mindycooky
设置这两个属性
year:要显示的年份
month:要显示的月份
********************************************
非常谢谢博主及时的回复!
你的代码写的挺好的,我做的项目中引用了,祝你工作顺利!
回复 引用 查看
#56楼[楼主] 2009-11-13 08:21 cloudgamer
@mindycooky
谢谢支持
回复 引用 查看
#57楼 2009-12-02 15:41 流风--回雪
楼主我已经在项目中采用你的日历,写的真的很好,尤其是提供了一些接口,扩展性相当的棒!
回复 引用
#58楼 2010-10-27 10:17 vai[未注册用户]
var $ = function (id) {
return "string" == typeof id ? document.getelementbyid(id) : id;
};
var class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
//将this对象和arguments参数放入initialize中
//return时候返回该对象
/*
这里坐下说明,例如 objecta有abc三个元素
当objecta.a去apply或者call objectb的时候假设里面包含d
组成是 就成了objecta有abcd并执行d
*/
}
}
}
object.extend = function(destination, source) {
for (var property in source) {
//将source对象覆盖到destination,然后return
destination[property] = source[property];
}
return destination;
}
lengwei,不知道能不能帮到你,虽然才开始看lz的博客,而且晚了一年
回复 引用 查看
#59楼 2010-12-12 15:16 penguin
哥们,厉害
回复 引用 查看
#60楼 2011-03-24 15:43 angxuan
实例中是固定了这个日期列表,实际应用中可以根据年份月份获取对应的日期列表,个人推荐用年份月份通过ajax获取。
==
此处的flag貌似无法通过ajax获取值,ajax内部flag有值,到外面for循环就不存在了,放在ajax内部循环更行不通.一时没查出什么原因。lz可试试,也可顺便给个回复
回复 引用 查看
#61楼[楼主] 2011-03-24 16:41 cloudgamer
@penguin
谢谢支持
回复 引用 查看
#62楼[楼主] 2011-03-24 16:47 cloudgamer
@angxuan
我就是放在ajax里面设置的 没发现问题
回复 引用 查看
#63楼 2011-03-24 17:00 angxuan
嗯,重新改了下,将构造new calendar及相关click方法置于ajax的success方法里搞定
回复 引用 查看
#64楼 2011-03-24 17:43 angxuan
可贴你ajax设置部分代码一看..
回复 引用
#65楼 2011-03-24 20:25 lollol[未注册用户]
错误: 'this.days' 为空或不是对象
回复 引用 查看
#66楼[楼主] 2011-03-24 23:07 cloudgamer
@lollol
这里没问题
回复 引用 查看
#67楼 2011-04-27 16:59 tech
预览了一下全部的js特效文章中的demo,很好,很强大
有时间来慢慢看
回复 引用
#68楼 2011-07-28 15:45 lolol[未注册用户]
求教,怎么实现一个输入日期的下拉菜单,第一个选择年份,第二个月份,关键是第三个,能自动判断某月的天数,谢谢啦
回复 引用 查看
#69楼[楼主] 2011-07-29 08:54 cloudgamer
@tech
谢谢支持
回复 引用 查看
#70楼[楼主] 2011-07-29 08:54 cloudgamer
@lolol
看这个
http://www.cnblogs.com/cloudgamer/archive/2008/10/28/1040403.html
回复 引用
#71楼 2011-07-29 15:31 lolol[未注册用户]
@cloudgamer
初学javascritp,谢谢指导。
回复 引用 查看
#72楼 2011-07-30 21:17 默^_^默
请问怎么得到星期几?
回复 引用 查看
#73楼[楼主] 2011-08-03 17:01 cloudgamer
@默^_^默
getday
回复 引用 查看
#74楼 2011-08-27 11:53 落碧
好东西感谢楼主分享...hoho
回复 引用 查看
#75楼 2011-12-19 14:40 飞船
有个建议,每次重绘日历控件都要重新creat这么多dom,是不是可以修改下,dom建立完成后,每次重绘改为每次只要填日期数据。要知道浏览器每次创建dom是很耗时的。楼主的控件不错,借鉴了。
发表评论
昵称: [登录]
主页:
邮箱:(仅博主可见)
验证码:看不清。
换一个
评论内容:
记住我的昵称和主页
-->
[使用ctrl+enter键快速提交评论]
0
1274459
oiqaevzdhxg=
最新it新闻:
» 更多新闻...
最新知识库文章:
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/