原文:javascript日历插件

javascript日历插件

最近在尝试着写javascript日历插件,所以也到github上看国外人日历源码,或者国内人写的好点的,也在研究点,虽然看到网上有一大把的日历控件,但是没有几个是自己想要的,虽然效果是实现了,但是看他们的源码,头有点大,所以自己也在研究这方面的东西。周末用了2天来研究别人写的代码 自己也试着做做demo,今天正好基本功能完成了,所以趁着这个机会分享下:我们可以先来看看效果:JSFiddler地址如下:

demo链接请点击我

基本的配置如下:

   targetCls
'',    输入框dom节点 默认为空 必填项
 beginyear 1978,     开始年份
 endyear  2050,    结束年份
 date  new Date(),  默认日期
 type  "yyyy-mm-dd" ,      日期格式(目前只支持这一种)
separator  '-' ,             日期链接符
wday  0 ,             周的第一天
language

{
year:"年",
month:"月",
monthList:["1","2","3","4","5","6","7","8","9","10","11","12"],
weekList:["日","一","二","三","四","五","六"]} // 默认为中文


方法如下:

1. show():  显示日历面板。

2. hide(): 隐藏日历面板。

3. clear() 清除输入框的日期。

4. getValue() 获取当前选中的日期。

5. 提供callback回调。返回一个参数(每当点击一项时候 返回输入框的值 即:日历的值)。

所有的JS代码如下:

/**
* javascript日历控件
*/ function Calendar(options,callback){
var self = this;
self.options = $.extend({},defaults,options || {});
self.targetCls = $(self.options.targetCls);
if(self.targetCls.length < 1) {return;}
self.language = self.options.language;
self.flag = false;
self.callback = callback; self._init();
self._bindEnv(); };
$.extend(Calendar.prototype,{ _init: function(){
var self = this;
// 先渲染日历面板
self._renderCalendarPanel();
},
_renderCalendarPanel: function(){
var self = this,
options = self.options;
// 如果input输入框有日期的话
if(self.targetCls.val().length > 0) {
self.date = self._dateParse(self.targetCls.val());
}
self.date = new Date(self.date);
if(isNaN(self.date.getFullYear())){
self.date = new Date();
}
var defYear = self.date.getFullYear(),
defMonth = self.date.getMonth() + 1,
defDay = self.date.getDate(); // 定义每月的天数
self.month_day = new Array(31,28+self._leapYear(defYear),31,30,31,30,31,31,30,31,30,31); // 定义每周的日期
self.date_name_week = self.language.weekList; // 定义周末
var saturday = 6 - options.wdays,
sunday = (7-options.wdays >= 7) ? 0 : (7-options.wday); // 创建日历面板dom节点
var date_pane = $('<div class="cxcalendar"></div>'),
date_hd = $('<div class="date_hd"></div>').appendTo(date_pane),
date_table = $('<table class="date_table"></table>').appendTo(date_pane);
date_hd.html("<a class='date_pre' href='javascript://' rel='prev'>&lt;</a><a class='date_next' href='javascript://' rel='next'>&gt;</a>"); var date_txt = $('<div class="date_txt"></div>').appendTo(date_hd),
date_set = $('<div class="date_set"></div>').appendTo(date_hd),
html = ""; for(var i = options.beginyear; i < options.endyear; i++) {
html +="<option value='"+i+"'>"+i+"</option>";
}
var year_list = $('<select class="year_set"></select>').html(html).appendTo(date_set).val(defYear); date_set.append(" - ");
html = '';
for(var i = 0; i < 12; i++) {
html += '<option value="'+(i+1)+'">'+self.language.monthList[i]+'</option>';
}
var month_list = $('<select class="month_set"></select>').html(html).appendTo(date_set).val(defMonth);
html = '<thead><tr>';
// 遍历一周7天
for(var i = 0; i < 7; i++) {
html += "<th class='"
// 周末高亮
if(i == saturday) {
html+= " sat";
}else if(i == sunday) {
html+= " sun";
};
html+="'>";
html+= (i+options.wday * 1 < 7) ? self.date_name_week[i+options.wday] : self.date_name_week[i+options.wday - 7];
html+="</th>";
};
html +="</tr></thead>";
html +="<tbody></tbody>";
date_table.html(html); // 面板及背景遮挡层插入到页面中
date_pane.appendTo("body"); // 创建遮罩层的目地是:只显示一个日历面板
var block_bg=$("<div class='cxcalendar_lock'></div>").appendTo("body"); // 赋值 全局
self.dateTxt = date_txt;
self.yearList = year_list;
self.monthList = month_list;
self.dateTable = date_table;
self.saturday = saturday;
self.sunday = sunday;
self.datePane = date_pane;
self.blockBg = block_bg;
self.dateSet = date_set;
self.defYear = defYear;
self.defMonth = defMonth; // 根据年份 月份来渲染天
self._renderBody(defYear,defMonth);
},
_dayNumOfMonth: function(Year,Month){
var d = new Date(Year,Month,0);
return d.getDate();
},
/*
* 渲染日历天数
* @param {y,m} 年 月
*/
_renderBody: function(y,m){
var self = this;
var options = self.options;
if(m < 1) {
y--;
m = 12;
}else if(m > 12) {
y++;
m = 1;
}
var tempM = m,
cur_m = m; m--; // 月份从0开始的
var prevMonth = tempM - 1, //上个月的月份
prevDay = self._dayNumOfMonth(y,tempM - 1), // 上个月的天数
nextMonth = tempM + 1, // 下个月的月份
nextDay = self._dayNumOfMonth(y,tempM + 1), //下个月的天数
curDay = self._dayNumOfMonth(y,tempM); // 当前月份的天数 self.month_day[1]=28+self._leapYear(y); //闰年的话 29天 否则 28天
var temp_html = "",
temp_date = new Date(y,m,1);
var now_date = new Date();
now_date.setHours(0);
now_date.setMinutes(0);
now_date.setSeconds(0); // 如果输入框有值的话
if(self.targetCls.val().length > 0) {
var val_date=self._dateParse(self.targetCls.val())
}
val_date=new Date(val_date);
if(isNaN(val_date.getFullYear())){
val_date=null;
};
// 获取当月的第一天
var firstDay = temp_date.getDay() - options.wday < 0 ? temp_date.getDay() - options.wday + 7 : temp_date.getDay() - options.wday;
// 每月所需要的行数
var monthRows = Math.ceil((firstDay+self.month_day[m]) / 7);
var td_num,
day_num,
diff_now,
diff_set;
var disabled;
for(var i= 0; i < monthRows; i++) {
temp_html += "<tr>";
for(var j = 0; j < 7; j++) {
td_num=i*7+j;
day_num=td_num-firstDay+1;
if(day_num<=0) {
if(day_num == 0) {
day_num = prevDay - day_num
text_m = prevMonth
}else {
day_num = prevDay + day_num;
text_m = prevMonth
} }else if(day_num > self.month_day[m]){
day_num = day_num - curDay;
text_m = nextMonth
}else {
text_m = cur_m;
}
temp_html+="<td";
if(typeof(day_num) == 'number') {
diff_now=null;
diff_set=null;
temp_date = new Date(y,m,day_num); if(text_m == cur_m) {
diff_now=Date.parse(now_date)-Date.parse(temp_date);
diff_set=Date.parse(val_date)-Date.parse(temp_date);
}
if(cur_m > text_m || cur_m < text_m) {
disabled = 'disabled';
}else {
disabled = "";
}
temp_html+=(" title='"+y+options.separator+tempM+options.separator+day_num+"' class='num "+disabled+""); // 高亮周末、今天、选中
if(diff_set==0){ //选中的时候 增加select 类名
temp_html+=" selected";
}else if(diff_now==0){
temp_html+=" now"; // 当前时间增加now类名
}else if(j==self.saturday){
temp_html+=" sat"; // 周六增加sat类名
}else if(j==self.sunday){
temp_html+=" sun"; // 周日增加sun类名
};
temp_html+=("'");
};
temp_html+=(" data-day='"+day_num+"'>"+day_num+"</td>");
}
temp_html+="</tr>";
}
$(self.dateTable).find("tbody").html(temp_html);
$(self.dateTxt).html("<span class='y'>"+y+"</span>"+options.language.year+"<span class='m'>"+options.language.monthList[m]+"</span>"+options.language.month);
$(self.yearList).val(y);
$(self.monthList).val(m+1); return this;
},
_dateParse: function(date){
var newdate = date;
newdate=newdate.replace(/\./g,"/");
newdate=newdate.replace(/-/g,"/");
newdate=newdate.replace(/\//g,"/");
newdate=Date.parse(newdate);
return newdate;
},
/*
* 判断是否是闰年
* @param y 年份
* 1.能被4整除且不能被100整除 2.能被100整除且能被400整除
*/
_leapYear: function(y) {
return ((y%4==0 && y%100!=0) || y%400==0) ? 1 : 0;
},
_bindEnv: function(){
var self = this;
$(self.targetCls).unbind('click').bind('click',function(){
self.show();
}); // 关闭面板事件
self.blockBg.unbind('click').bind("click",function(){
self.hide();
}); // 点击上一页 下一页事件
self.datePane.delegate('a','click',function(){
if(!this.rel){return};
var _rel = this.rel;
if(_rel == 'prev') {
self._renderBody(self.yearList.val(),parseInt(self.monthList.val(),10) -1);
return;
}else if(_rel == 'next') {
self._renderBody(self.yearList.val(),parseInt(self.monthList.val(),10) +1);
return;
}
}); // 选择日期事件
self.datePane.delegate('td','click',function(){
var _this = $(this);
if(_this.hasClass('num') && !_this.hasClass('disabled')) {
self.dateTable.find("td").removeClass("selected");
_this.addClass("selected");
var day = _this.attr("data-day");
self._selectDay(day);
}
}); // 显示年月选择
self.dateTxt.unbind('click').bind("click",function(){
self.dateTxt.hide();
self.dateSet.show();
}); //更改年月事件
self.yearList.unbind('change').bind("change",function(){
self._renderBody(self.yearList.val(),self.monthList.val());
});
self.monthList.unbind('change').bind("change",function(){
self._renderBody(self.yearList.val(),self.monthList.val());
});
},
/*
* 选择某一天的时候 把值存入输入框里 且面板隐藏
* @_selectDay {private}
*/
_selectDay: function(d) {
var self = this;
var year,
month;
month = self.monthList.val();
day = d;
var options = self.options;
if(options.type == 'yyyy-mm-dd') {
month="0" + self.monthList.val();
day= "0" + d;
month=month.substr((month.length-2),month.length);
day=day.substr((day.length-2),day.length);
}
self.targetCls.val(self.yearList.val()+options.separator+month+options.separator+day);
self.hide(); self.callback && $.isFunction(self.callback) && self.callback(self.yearList.val()+options.separator+month+options.separator+day);
return this;
},
/*
* 显示日历面板
* @method show {public}
*/
show: function(){
var self = this;
if(self.flag) {
return;
}
var doc_w = document.body.clientWidth,
doc_h = document.body.clientHeight,
pane_top = self.targetCls.offset().top,
pane_left = self.targetCls.offset().left,
obj_w = self.targetCls.outerWidth(),
obj_h = self.targetCls.outerHeight();
pane_top= pane_top+obj_h;
self.datePane.css({"top":pane_top,"left":pane_left}).show();
self.blockBg.css({width:doc_w,height:doc_h}).show();
self.flag = true;
return this;
},
/*
* 清除日期
* @method clear {public}
*/
clear: function(){
var self = this;
self.targetCls.val('');
self._renderBody(self.defYear,self.defMonth);
self.hide();
return this;
},
/*
* 获取当前选中的日期
* @method getValue {public}
* @return val
*/
getValue: function(){
var self = this;
return self.targetCls.val();
},
/*
* 隐藏日历面板
*/
hide: function(){
var self = this;
if(!self.flag) {return;}
self.datePane.hide();
self.blockBg.hide();
self.dateSet.hide();
self.dateTxt.show();
self.flag = false;
return this;
}
}); var defaults = {
targetCls : '', //渲染日历的class
beginyear : 1978, //开始年份
endyear : 2050, //结束年份
date : new Date(), // 默认日期
type : "yyyy-mm-dd", // 日期格式
separator : "-", // 日期链接符
wday : 0, // 周第一天
language : {
year:"年",
month:"月",
monthList:["1","2","3","4","5","6","7","8","9","10","11","12"],
weekList:["日","一","二","三","四","五","六"]}
};

代码没有什么好解释的 相应的有注释,可以看看源码 不难的。

HTML代码可以这样写:

我是时间控件1:<input name="mydate" type="text" class="input_cxcalendar" readonly style="width:200px;">

初始化代码如下:

$('.input_cxcalendar').each(function(){
var a = new Calendar({
targetCls: $(this)
},function(val){
console.log(val);
});
});

日历控件demo下载

javascript日历插件的更多相关文章

  1. Javascript 日历插件

    1. The Coolest Calendar 界面非常漂亮的一款日期选择插件,有详细的使用文档,最新版本 1.5. 点击下载    查看示例 2. DatePicker 这款日期插件支持单选.多选和 ...

  2. 11个顶级 JavaScript 日历插件

    参考链接:https://mp.weixin.qq.com/s?__biz=MzI3NzIzMDY0NA==&mid=2247487050&idx=1&sn=e1cf66726 ...

  3. 完全原生javascript简约日历插件,js、html

    效果图: 效果如图所示,尽管看上去并不是很美观,但是,基本上的功能还是已经完成了,码了一天多的时间,权当做复习一下js吧. 整个做下来差不多码了500多行代码~其实只是很多的样式也包括了在其中了,虽然 ...

  4. 日历插件FullCalendar应用:(二)数据增删改

    接上一篇 日历插件FullCalendar应用:(一)数据展现. 这一篇主要讲使用fullcalendar插件如何做数据的增删改,用到了art.dialog web对话框组件,上一篇用到的webFor ...

  5. 一款基于jQuery日历插件的开发过程

    这个插件的设置选项,所有样式都设置成自定义,提供回调函数,方便在外部进行扩展 css设置是可变的  也就是说  日历的样式是定制的: /******************************** ...

  6. 一款简洁大气的jquery日期日历插件

    本jquery插件名为manhuaDate,暂时只支持jquery 1.9.0以下版本,比如jquery-1.8.3.min.js 查看效果网址:http://keleyi.com/a/bjad/em ...

  7. 【UI插件】简单的日历插件(下)—— 学习MVC思想

    前言 我们上次写了一个简单的日历插件,但是只是一个半成品,而且做完后发现一些问题,于是我们今天尝试来解决这些问题 PS:距离上次貌似很久了 上次,我们大概遇到哪些问题呢: ① 既然想做一套UI库,那么 ...

  8. 【UI插件】开发一个简单日历插件(上)

    前言 最近开始整理我们的单页应用框架了,虽然可能比不上MVVM模式的开发效率,也可能没有Backbone框架模块清晰,但是好歹也是自己开发出来 而且也用于了这么多频道的东西,如果没有总结,没有整理,没 ...

  9. 【特别推荐】几款极好的 JavaScript 下拉列表插件

    表单元素让人爱恨交加.作为网页最重要的组成部分,表单几乎无处不在,从简单的邮件订阅.登陆注册到复杂的需要多页填写的信息提交功能,表单都让开发者花费了大量的时间和精力去处理,以期实现好用又漂亮的表单功能 ...

随机推荐

  1. div+js 弹出层

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...

  2. 如此的相似,不能-------Day84

    生活中我们会遇到一些相似事儿,它可能是一个项目,我发现,你失去非常相似,其结果是不,它可以是人.你认为你一直在等待的是他(她),终于可以找到,只需简单地认为.正是这样相似. js和java语言中有不少 ...

  3. UWP开发的一些思考

    UWP开发的一些思考 领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中 ...

  4. 移动端 touchmove高频事件与requestAnimationFrame的结合优化

    移动端最高频耗内存的的操作  莫属 touchmove 与scroll事件  两者需要 微观的 优化,使用 requestAnimationFrame性能优化 H5性能优化requestAnimati ...

  5. C++ tree(1)

    建立与基本操作 .有关二叉树的相关概念,这里不再赘述,假设不了解二叉树相关概念,建议先学习数据结构中的二叉树的知识点 准备数据 定义二叉树结构操作中须要用到的变量及数据等. #define MAXLE ...

  6. linux添加到普通用户sudo才干

    在超级用户模式添加到普通用户sudo才干 1. su -(进root用户) 2. chmod u+w /etc/sudoer 3. vim /etc/sudoers 于root ALL=(ALL) A ...

  7. WPF学习(12)动画

    本篇来学习WPF的动画.什么是动画?动画就是一系列帧.在WPF中,动画就是在一段时间内修改依赖属性值的行为,它是基于时间线Timeline的.有人会说,要动画干嘛,华而不实,而且添加了额外的资源消耗而 ...

  8. 跟着辛星认识一下PHP的自己主动载入

    作为一个框架,文件的载入机制是不能少的,那么我们应该怎么载入呢,这些PHP已经给我们想好了,所以我们仅仅须要依照规则办事就能够了,PHP中有两个函数能够完毕这个功能,第一个是__autoload,如今 ...

  9. Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质

    原文:Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质 Linux内核分析(六) 昨天我们对字符设备进行了初步的了解,并且实现了简单的字符设备驱动,今天我们继续对字符设备的某些方 ...

  10. 为网站添加IE6升级提示

    原文 为网站添加IE6升级提示 IE6的是一款横跨十年的浏览器,作为一枚前端,对其已经失望透顶,但其在中国的市场比仍旧很高,中国大量的PC上安装的都是盗版Windows XP,而Windows XP上 ...