该日历选择控件由tiannet根据前人经验完善而得。大部分代码来自meizz的日历控件。
上面那句话是所使用的riqi.js中声明的,因为找不到类似于转载链接一样的URL,只能原封不动的声明了。
这个日历控件,是在源文件的基础上改进的,至于源文件哪有,长什么样,我实在是不知道。另外,这个控件只能用于平面展示日期及加载每月哪天有数据之外,不提供选择数据的动能。OK,废话到此为止,直接上代码吧。
1、需要引入的css和js:
<link type="text/css" rel="stylesheet" href="riqi.css"/>
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript" src="jquery.mousewheel.js"></script>
<script type="text/javascript" src="riqi.js" charset="utf-8"></script>
<script type="text/javascript" src="sub.js"></script>
说明一下:
a、riqi.css是用到的样式文件,jquery-1.4.2.js是Jquery用的包,大家都知道
b、jquery.mousewheel.js是处理滚轮用的,也就是当鼠标放在日历控件上滚动滚轮时自动切换月份
c、riqi.js用来拼接日历控件
d、sub.js用来协调页面和riqi.js,也就是判断什么时候加载,什么时候滚轮啥的。
2、页面:页面很简单,给个div定位就行,样式文件在riqi.css中:
<body>
<div id="divTiannetCalendar" class="divdata"></div>
</body>
/**
*本日历选择控件由tiannet根据前人经验完善而得。大部分代码来自meizz的日历控件。
*tiannet添加了时间选择功能、select,object标签隐藏功能,还有其它小功能。
*使用方法:
* (1)只选择日期 <input type="text" name="date" readOnly onClick="setDay(this);">
* (2)选择日期和小时 <input type="text" name="dateh" readOnly onClick="setDayH(this);">
* (3)选择日期和小时及分钟 <input type="text" name="datehm" readOnly onClick="setDayHM(this);">
*设置参数的方法
* (1)设置日期分隔符 setDateSplit(strSplit);默认为"-"
* (2)设置日期与时间之间的分隔符 setDateTimeSplit(strSplit);默认为" "
* (3)设置时间分隔符 setTimeSplit(strSplit);默认为":"
* (4)设置(1),(2),(3)中的分隔符 setSplit(strDateSplit,strDateTimeSplit,strTimeSplit);
* (5)设置开始和结束年份 setYearPeriod(intDateBeg,intDateEnd)
*说明:
* 默认返回的日期时间格式如同:2005-02-02 08:08
*/
//------------------ 变量定义 ---------------------------//
var tiannetYearSt2 = 1950;//可选择的开始年份
var tiannetYearEnd2 = 2030;//可选择的结束年份
var tiannetDateNow2 = new Date();
var tiannetYear2 = tiannetDateNow2.getFullYear(); //定义年的变量的初始值
var tiannetMonth2 = tiannetDateNow2.getMonth() + 1; //定义月的变量的初始值
var tiannetDay2 = tiannetDateNow2.getDate();
var tiannetHour2 = tiannetDateNow2.getHours();
var tiannetMinute2 = tiannetDateNow2.getMinutes();
var tiannetArrDay2 = new Array(42); //定义写日期的数组
var tiannetDateSplit2 = "-"; //日期的分隔符号
var tiannetDateTimeSplit2 = " "; //日期与时间之间的分隔符
var tiannetTimeSplit2 = ":"; //时间的分隔符号
var tiannetOutObject2; //接收日期时间的对象
var arrTiannetHide2 = new Array();//被强制隐藏的标签
var m_bolShowHour2 = false;//是否显示小时
var m_bolShowMinute2 = false;//是否显示分钟
var m_aMonHead2 = new Array(12); //定义阳历中每个月的最大天数
m_aMonHead2[0] = 31;
m_aMonHead2[1] = 28;
m_aMonHead2[2] = 31;
m_aMonHead2[3] = 30;
m_aMonHead2[4] = 31;
m_aMonHead2[5] = 30;
m_aMonHead2[6] = 31;
m_aMonHead2[7] = 31;
m_aMonHead2[8] = 30;
m_aMonHead2[9] = 31;
m_aMonHead2[10] = 30;
m_aMonHead2[11] = 31;
var tdNum2=35;//用来记录循环数,即日历控件中td的个数
/**
* 拼接日历的HTML
* */
var weekName2 = new Array("一", "二", "三", "四", "五", "六","日");
/**
* 拼接日历控件
* @param yy:年份(没有时使用当前年份)
* @param mm:月份(没有时使用当前月份)
* @param userId:当前登录人序号,需要根据当前登录人的信息来加载本人的日程数据
* @return html
* */
function getDayHTML(yy,mm,userId){
var html="";
//初始化年月
this.initYearAndMonth(yy,mm);
//初始化数组值
this.initCalendarArray();
html+="<div align='center' id='divTiannetCalendarText' Author='tiannet'>";
html+="<span id='tiannetCalendarYearHead' class='year_0' Author='tiannet' onclick='showNextUL(this,1);'>"+tiannetYear2+"年</span>";
html+="<div class='yearalert'><ul>";
for ( var i = tiannetYearSt2; i <= tiannetYearEnd2; i++) {
html+="<li optValue='"+(i)+"' onclick='showPrevSpan(this,1);'>"+(i)+"年</li>";
}
html+='</ul></div>';
html+="<span id='tiannetCalendarMonthHead' class='month_0' Author='tiannet' onclick='showNextUL(this,2);'>"+tiannetMonth2+"月</span>";
html+="<div class='monthalert'><ul>";
for ( var i = 1; i <= 12; i++) {
html+="<li optValue='"+i+"' onclick='showPrevSpan(this,2);'>"+i+"月</li>";
}
html+="</ul></div>";
html+="<span id='backToToday' class='backToToday' onclick='backToToday();'>返回今天</span></div>";
html+="<div class='clear'></div>"
html+="<table border=0 cellspacing=0 cellpadding=0 bgcolor=white class='weekday' >";
html+="<tr Author='tiannet'>";
for ( var i = 0; i < weekName2.length; i++) {//输出星期
html+="<td align='center' Author='tiannet'>"+weekName2[i]+"</td>";
}
html+="</tr>";
html+="</table>";
//输出天的选择
html+="<table border=0 cellspacing=0 cellpadding=0 bgcolor=white class='datato'>";
var n = 0;
var strDateFont1 = "", strDateFont2 = "",tdVal="",className="",result=""; //处理日期显示的风格
if(userId==null || userId=='' || userId==1){//若为空或管理员,那么不查询,也就是只加载日历不加载日程数据
result="";
}else{
var date = tiannetYear2+"-"+tiannetMonth2+"-1";
//获取当前月份的待办事项所属天
$.ajax({
url:"tools!getTaskCount.action",
async:false,
type:"post",
dataType:"text",
data:{"date":date,"times":new Date().getTime()},
timeout:4000,
error:function(C){
alert(C);
},
success:function(data){
if(data==false || data=="false"){
result="";
}else{
result=data;
}
}
});
}
//必须添加最后的逗号,因为得到的格式为:,天,天,天,添加最后的逗号之后才可以用indexOf(,天,)来判断
result=jQuery.trim((result+","));
for ( var i = 0; i < tdNum2; i++) {
className="notselday";
if (tiannetArrDay2[i] != ""){//说明当前值不为空
//判断是否为周末,如果是周末,则改为红色字体
if ((i + 1) % 7== 0 || (i + 2) % 7 == 0) {
strDateFont1 = "<font>"
strDateFont2 = "</font>"
} else {
strDateFont1 = "";
strDateFont2 = ""
}
tdVal = strDateFont1 + tiannetArrDay2[i] + strDateFont2;
//如果是当前选择的天,则改变颜色
if (tiannetArrDay2[i] == tiannetDay2) {
className="curday";//当前选择的天
}
//若当前天上有待办事项,则改变颜色
if((result.indexOf(","+tiannetArrDay2[i]+",")!=-1)){
className="selday";//有待办事项
}
if(tiannetArrDay2[i] == tiannetDay2 && (result.indexOf(","+tiannetArrDay2[i]+",")!=-1)){//如果以上两种情况都符合
className="curAndSelday";
}
} else {
tdVal="";
className="blankday";//空白天数
}
if (i==0 || (i) % 7 == 0) {//说明已经是一行了
html+="<tr align='center' id='trTiannetCalendarDay"+(n)+"'>";
html+="<td align='center' class='"+className+"' id='tdTiannetCalendarDay"+(i)+"'>"+(tdVal)+"</td>";
n++;
}else{
html+="<td align='center' class='"+className+"' id='tdTiannetCalendarDay"+(i)+"'>"+(tdVal)+"</td>";
}
if(n<(i/7)){
html+=' </tr>';
}
}
html+='</table>';
return html;
}
//初始化年月
function initYearAndMonth(yy,mm){
//若年份和月份都不存在,那么使用当前年份和月份
if(yy==null || yy==""){
yy=tiannetYear2;
}else{//若存在,那么将当前年月设置成显示的
tiannetYear2=yy;
}
if(mm==null || mm==""){
mm=tiannetMonth2;
}else{
tiannetMonth2=mm;
}
}
//初始化需要显示数据的数组值
function initCalendarArray() {
setRealDayCount2();//设置当月真实的日
var day1 = 1;
var firstday = new Date(tiannetYear2, tiannetMonth2 - 1, 0).getDay(); //某月第一天的星期几
tdNum2 =firstday+this.getMonthCount2(tiannetYear2, tiannetMonth2);
if(tdNum2 % 7!=0){//若不能整除,那么向下取整加1
// alert(Math.floor(tdNum2/7));
tdNum2 = (Math.floor(tdNum2/7)+1)*7;
}
//初始化日历数组
for ( var i = 0; i < tdNum2; i++) {
tiannetArrDay2[i] = ""
}
for ( var i = firstday; day1<=this.getMonthCount2(tiannetYear2, tiannetMonth2) ; i++) {
tiannetArrDay2[i] = day1;
day1++;
}
}
//得到一个月的天数,闰年为29天
function getMonthCount2(year, month) {
var c = m_aMonHead2[month - 1];
if ((month == 2) && this.isPinYear2(year))
c++;
return c;
}
//重新设置当前的日。主要是防止在翻年、翻月时,当前日大于当月的最大日
function setRealDayCount2() {
if (tiannetDay2 > this.getMonthCount2(tiannetYear2, tiannetMonth2)) {
//如果当前的日大于当月的最大日,则取当月最大日
tiannetDay2 = this.getMonthCount2(tiannetYear2, tiannetMonth2);
}
}
//判断某年是否为闰年
function isPinYear2(year) {
var bolRet = false;
if (0 == year % 4 && ((year % 100 != 0) || (year % 400 == 0))) {
bolRet = true;
}
return bolRet;
}
/**
* 点击年或月时触发该事件用来显示DIV
* @param obj:当前span
* @param flag:1-年 2-月
* */
function showNextUL(obj,flag){
var $obj,className="",className2="";
if(flag==1){//点的是年,那么需要先隐藏月所在div,并移除月span中的class
$obj=$(".monthalert");
className="month_1";
className2="year_1";
}else{
$obj=$(".yearalert");
className="year_1";
className2="month_1";
}
//1、隐藏其他节点的下拉项所在DIV
$obj.hide();
$obj.prev("span").removeClass(className);
//2、隐藏或显示
var $next = $(obj).next();
if($next.is(":visible")){//处于显示状态
$next.hide();//隐藏
$(obj).removeClass(className2);
}else{
$next.show();
$(obj).addClass(className2);
//添加鼠标在上和移开事件
$next.mouseenter(function(){
}).mouseleave(function(){
$next.hide();
$(obj).removeClass(className2);
});
}
}
/**
* 点击UL下的li时触发该事件,需要处理如下几件事:
* 1、为span赋值 2、隐藏当前UL所在DIV 3、重新加载日历
* @param obj:当前LI
* @param flag:1-年 2-月
*/
function showPrevSpan(obj,flag){
var t = "",v="",className="";
if(flag==1){
t="年";
tiannetYear2=$(obj).attr("optValue");
v=tiannetYear2;
className="year_1";
}else{
t="月";
tiannetMonth2=$(obj).attr("optValue");
v=tiannetMonth2;
className="month_1";
}
var $parent = $(obj).parent().parent();//DIV
if(typeof v=="undefined")v=0;
$parent.prev("span").text(v+t);
$parent.prev("span").removeClass(className);
$parent.hide();
loadCalendar(tiannetYear2,tiannetMonth2);
}
/**
* 获取当前年月
*/
function getYearAndMonth(){
return [tiannetYear2,tiannetMonth2];
}
PS:这个riqi控件原本是用来加载每个月的待办事项数据的(代码中使用AJAX加载数据那段),若没有相关应用,可以去掉相应代码,或者在调用该方法时,将第三个参数设置为空
4、辅助类sub.js:
$(function(){
//加载日历控件
loadCalendar("","");//没有参数值使用默认参数:当前年份和月份
//为日历控件绑定滚轮效果
calendarMouseWheel();
});
/**
* 加载日历控件
* @param yy:年份(没有时使用当前年份)
* @param mm:月份(没有时使用当前月份)
* */
function loadCalendar(yy,mm){
var html = getDayHTML(yy,mm,1);
$("#divTiannetCalendar").html(html);
}
/**
* 为日历控件绑定滚轮效果
* 加上延迟主要是为了解决:鼠标滚动一下就会执行当前方法一次,当鼠标滚轮过快时,
* 就会连续触发该事件,造成“滚动一次鼠标,月份多月跳动”的情况,
* 即滚动之前是1月,滚轮一次后变成3月或4月或5月
* */
function calendarMouseWheel(){
$("#divTiannetCalendar").bind('mousewheel', function(event, delta, deltaX, deltaY){
//delta为1向上滚动 delta为-1向下滚动
//alert("delta="+delta+" deltaX="+deltaX+" deltaY="+deltaY);
var $this = $(this),
timeoutId = $this.data('timeoutId');
if (timeoutId) {
clearTimeout(timeoutId);
}
$this.data('timeoutId', setTimeout(function() {
var yearAndMonth= getYearAndMonth();
var year = yearAndMonth[0];
var month = yearAndMonth[1];
if(delta<0){//说明向下滚动那么向下翻页
month=month+1;
if(month>12){
month=1;
year=year+1;
}
}else{//向上滚
month=month-1;
if(month<1){
month=12;
year=year-1;
}
}
$("#tiannetCalendarYearHead").text(year+"年");
$("#tiannetCalendarMonthHead").text(month+"月");
loadCalendar(year,month);
$this.removeData('timeoutId');
$this = null;
}, 100));
return false;
});
}
/**
* 点击“返回今天”字样时触发该事件,该事件用来返回当前月的数据信息
* */
function backToToday(){
var today = new Date();
var y = today.getFullYear();//获取当前年份
var m = today.getMonth()+1;//获取当前月份
loadCalendar(y,m);//加载数据
}
PS:鼠标滚轴的思想是参考别人的,具体地址等找到了,再附上,嘿嘿。