您的位置:首页 > Web前端 > JQuery

基于jQuery的日期选择控件

2009-10-27 00:00 811 查看
但是也有些问题,第一画日历有点慢,第二兼容性不太好IE Only,第三它不是基于jQuery的哈哈。

那还是老规矩,做之前先看下效果






这下是更酷的Ext风格了。
从上图我们可以看出这个控件其实有两个视图一个日期月视图,还有一个是年月选择视图。
1:还是先从HTML入手

日期控件确定HTML其实还是比较简单,因为明摆着是列表的数据格式,当然主要是采用table了。
两个视图分别用两个Div包裹,控制div的显示隐藏即可以切换视图了。完整的HTMl结构大家可以用IEDeveloper看一下Demo的结构,我自己截了一个图



2:根据HTML和效果图编写CSS
其实因为是Ext风格的,所以直接copy的ext的css和图片。。
CSS也就不分析了,直接上代码。
因为博客园的语法高亮不支持CSS,所以就不贴出来了,给个下载地址吧:
所有用到的图片:







3:搞定了CSS之后呢,就开始编写我们javascript了。
上来就是一个完整代码
;(function($) { 
var userAgent = window.navigator.userAgent.toLowerCase(); 
$.browser.msie8 = $.browser.msie && /msie 8\.0/i.test(userAgent); 
$.browser.msie7 = $.browser.msie && /msie 7\.0/i.test(userAgent); 
$.browser.msie6 = !$.browser.msie8 && !$.browser.msie7 && $.browser.msie && /msie 6\.0/i.test(userAgent); 
Date.prototype.Format = function(format) { 
var o = { 
"M+": this.getMonth() + 1, 
"d+": this.getDate(), 
"h+": this.getHours(), 
"H+": this.getHours(), 
"m+": this.getMinutes(), 
"s+": this.getSeconds(), 
"q+": Math.floor((this.getMonth() + 3) / 3), 
"w": "0123456".indexOf(this.getDay()), 
"S": this.getMilliseconds() 
}; 
if (/(y+)/.test(format)) { 
format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 
} 
for (var k in o) { 
if (new RegExp("(" + k + ")").test(format)) 
format = format.replace(RegExp.$1, 
RegExp.$1.length == 1 ? o[k] : 
("00" + o[k]).substr(("" + o[k]).length)); 
} 
return format; 
}; 
function DateAdd(interval, number, idate) { 
number = parseInt(number); 
var date; 
if (typeof (idate) == "string") { 
date = idate.split(/\D/); 
eval("var date = new Date(" + date.join(",") + ")"); 
} 
if (typeof (idate) == "object") { 
date = new Date(idate.toString()); 
} 
switch (interval) { 
case "y": date.setFullYear(date.getFullYear() + number); break; 
case "m": date.setMonth(date.getMonth() + number); break; 
case "d": date.setDate(date.getDate() + number); break; 
case "w": date.setDate(date.getDate() + 7 * number); break; 
case "h": date.setHours(date.getHours() + number); break; 
case "n": date.setMinutes(date.getMinutes() + number); break; 
case "s": date.setSeconds(date.getSeconds() + number); break; 
case "l": date.setMilliseconds(date.getMilliseconds() + number); break; 
} 
return date; 
}; 
$.fn.datepicker = function(o) { 
var def = { 
weekStart: 0, 
weekName: ["日", "一", "二", "三", "四", "五", "六"], //星期的格式 
monthName: ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"], //月份的格式 
monthp: "月", 
Year: new Date().getFullYear(), //定义年的变量的初始值 
Month: new Date().getMonth() + 1, //定义月的变量的初始值 
Day: new Date().getDate(), //定义日的变量的初始值 
today: new Date(), 
btnOk: " 确定 ", 
btnCancel: " 取消 ", 
btnToday: "今天", 
inputDate: null, 
onReturn: false, 
version: "1.1", 
applyrule: false, //function(){};return rule={startdate,endate}; 
showtarget: null, 
picker: "" 
}; 
$.extend(def, o); 
var cp = $("#BBIT_DP_CONTAINER"); 
if (cp.length == 0) { 
var cpHA = []; 
cpHA.push("<div id='BBIT_DP_CONTAINER' class='bbit-dp' style='width:175px;z-index:999;'>"); 
if ($.browser.msie6) { 
cpHA.push('<iframe style="position:absolute;z-index:-1;width:100%;height:100%;top:0;left:0;scrolling:no;" frameborder="0" src="about:blank"></iframe>'); 
} 
cpHA.push("<table class='dp-maintable' cellspacing='0' cellpadding='0' style='width:175px;'><tbody><tr><td>"); 
//头哟 
cpHA.push("<table class='bbit-dp-top' cellspacing='0'><tr><td class='bbit-dp-top-left'> <a id='BBIT_DP_LEFTBTN' href='javascript:void(0);' title='向前一个月'> </a></td><td class='bbit-dp-top-center' align='center'><em><button id='BBIT_DP_YMBTN'>九月 2009</button></em></td><td class='bbit-dp-top-right'><a id='BBIT_DP_RIGHTBTN' href='javascript:void(0);' title='向后一个月'> </a></td></tr></table>"); 
cpHA.push("</td></tr>"); 
cpHA.push("<tr><td>"); 
//周 
cpHA.push("<table id='BBIT_DP_INNER' class='bbit-dp-inner' cellspacing='0'><thead><tr>"); 
//生成周 
for (var i = def.weekStart, j = 0; j < 7; j++) { 
cpHA.push("<th><span>", def.weekName[i], "</span></th>"); 
if (i == 6) { i = 0; } else { i++; } 
} 
cpHA.push("</tr></thead>"); 
//生成tBody,需要重新生成的 
cpHA.push("<tbody></tbody></table>"); 
//生成tBody结束 
cpHA.push("</td></tr>"); 
cpHA.push("<tr><td class='bbit-dp-bottom' align='center'><button id='BBIT-DP-TODAY'>", def.btnToday, "</button></td></tr>"); 
cpHA.push("</tbody></table>"); 
//输出下来框 
cpHA.push("<div id='BBIT-DP-MP' class='bbit-dp-mp' style='z-index:auto;'><table id='BBIT-DP-T' style='width: 175px; height: 193px' border='0' cellspacing='0'><tbody>"); 
cpHA.push("<tr>"); 
//1月,7月 按钮两个 
cpHA.push("<td class='bbit-dp-mp-month' xmonth='0'><a href='javascript:void(0);'>", def.monthName[0], "</a></td><td class='bbit-dp-mp-month bbit-dp-mp-sep' xmonth='6'><a href='javascript:void(0);'>", def.monthName[6], "</a></td><td class='bbit-dp-mp-ybtn' align='middle'><a id='BBIT-DP-MP-PREV' class='bbit-dp-mp-prev'></a></td><td class='bbit-dp-mp-ybtn' align='middle'><a id='BBIT-DP-MP-NEXT' class='bbit-dp-mp-next'></a></td>"); 
cpHA.push("</tr>"); 
cpHA.push("<tr>"); 
cpHA.push("<td class='bbit-dp-mp-month' xmonth='1'><a href='javascript:void(0);'>", def.monthName[1], "</a></td><td class='bbit-dp-mp-month bbit-dp-mp-sep' xmonth='7'><a href='javascript:void(0);'>", def.monthName[7], "</a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td>"); 
cpHA.push("</tr>"); 
cpHA.push("<tr>"); 
cpHA.push("<td class='bbit-dp-mp-month' xmonth='2'><a href='javascript:void(0);'>", def.monthName[2], "</a></td><td class='bbit-dp-mp-month bbit-dp-mp-sep' xmonth='8'><a href='javascript:void(0);'>", def.monthName[8], "</a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td>"); 
cpHA.push("</tr>"); 
cpHA.push("<tr>"); 
cpHA.push("<td class='bbit-dp-mp-month' xmonth='3'><a href='javascript:void(0);'>", def.monthName[3], "</a></td><td class='bbit-dp-mp-month bbit-dp-mp-sep' xmonth='9'><a href='javascript:void(0);'>", def.monthName[9], "</a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td>"); 
cpHA.push("</tr>"); 
cpHA.push("<tr>"); 
cpHA.push("<td class='bbit-dp-mp-month' xmonth='4'><a href='javascript:void(0);'>", def.monthName[4], "</a></td><td class='bbit-dp-mp-month bbit-dp-mp-sep' xmonth='10'><a href='javascript:void(0);'>", def.monthName[10], "</a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td>"); 
cpHA.push("</tr>"); 
cpHA.push("<tr>"); 
cpHA.push("<td class='bbit-dp-mp-month' xmonth='5'><a href='javascript:void(0);'>", def.monthName[5], "</a></td><td class='bbit-dp-mp-month bbit-dp-mp-sep' xmonth='11'><a href='javascript:void(0);'>", def.monthName[11], "</a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td><td class='bbit-dp-mp-year'><a href='javascript:void(0);'></a></td>"); 
cpHA.push("</tr>"); 
cpHA.push("<tr class='bbit-dp-mp-btns'>"); 
cpHA.push("<td colspan='4'><button id='BBIT-DP-MP-OKBTN' class='bbit-dp-mp-ok'>", def.btnOk, "</button><button id='BBIT-DP-MP-CANCELBTN' class='bbit-dp-mp-cancel'>", def.btnCancel, "</button></td>"); 
cpHA.push("</tr>"); 
cpHA.push("</tbody></table>"); 
cpHA.push("</div>"); 
cpHA.push("</div>"); 
var s = cpHA.join(""); 
$(document.body).append(s); 
var cp = $("#BBIT_DP_CONTAINER"); 
initevents(); 
} 
function initevents() { 
//1 today btn; 
$("#BBIT-DP-TODAY").click(returntoday); 
cp.click(returnfalse); 
$("#BBIT_DP_INNER tbody").click(tbhandler); 
$("#BBIT_DP_LEFTBTN").click(prevm); 
$("#BBIT_DP_RIGHTBTN").click(nextm); 
$("#BBIT_DP_YMBTN").click(showym); 
$("#BBIT-DP-MP").click(mpclick); 
$("#BBIT-DP-MP-PREV").click(mpprevy); 
$("#BBIT-DP-MP-NEXT").click(mpnexty); 
$("#BBIT-DP-MP-OKBTN").click(mpok); 
$("#BBIT-DP-MP-CANCELBTN").click(mpcancel); 
} 
function mpcancel() { 
$("#BBIT-DP-MP").animate({ top: -193 }, { duration: 200, complete: function() { $("#BBIT-DP-MP").hide(); } }); 
return false; 
} 
function mpok() { 
def.Year = def.cy; 
def.Month = def.cm + 1; 
def.Day = 1; 
$("#BBIT-DP-MP").animate({ top: -193 }, { duration: 200, complete: function() { $("#BBIT-DP-MP").hide(); } }); 
writecb(); 
return false; 
} 
function mpprevy() { 
var y = def.ty - 10 
def.ty = y; 
rryear(y); 
return false; 
} 
function mpnexty() { 
var y = def.ty + 10 
def.ty = y; 
rryear(y); 
return false; 
} 
function rryear(y) { 
var s = y - 4; 
var ar = []; 
for (var i = 0; i < 5; i++) { 
ar.push(s + i); 
ar.push(s + i + 5); 
} 
$("#BBIT-DP-MP td.bbit-dp-mp-year").each(function(i) { 
if (def.Year == ar[i]) { 
$(this).addClass("bbit-dp-mp-sel"); 
} 
else { 
$(this).removeClass("bbit-dp-mp-sel"); 
} 
$(this).html("<a href='javascript:void(0);'>" + ar[i] + "</a>").attr("xyear", ar[i]); 
}); 
} 
function mpclick(e) { 
var panel = $(this); 
var et = e.target || e.srcElement; 
var td = getTd(et); 
if (td == null) { 
return false; 
} 
if ($(td).hasClass("bbit-dp-mp-month")) { 
if (!$(td).hasClass("bbit-dp-mp-sel")) { 
var ctd = panel.find("td.bbit-dp-mp-month.bbit-dp-mp-sel"); 
if (ctd.length > 0) { 
ctd.removeClass("bbit-dp-mp-sel"); 
} 
$(td).addClass("bbit-dp-mp-sel") 
def.cm = parseInt($(td).attr("xmonth")); 
} 
} 
if ($(td).hasClass("bbit-dp-mp-year")) { 
if (!$(td).hasClass("bbit-dp-mp-sel")) { 
var ctd = panel.find("td.bbit-dp-mp-year.bbit-dp-mp-sel"); 
if (ctd.length > 0) { 
ctd.removeClass("bbit-dp-mp-sel"); 
} 
$(td).addClass("bbit-dp-mp-sel") 
def.cy = parseInt($(td).attr("xyear")); 
} 
} 
return false; 
} 
function showym() { 
var mp = $("#BBIT-DP-MP"); 
var y = def.Year; 
def.cy = def.ty = y; 
var m = def.Month - 1; 
def.cm = m; 
var ms = $("#BBIT-DP-MP td.bbit-dp-mp-month"); 
for (var i = ms.length - 1; i >= 0; i--) { 
var ch = $(ms[i]).attr("xmonth"); 
if (ch == m) { 
$(ms[i]).addClass("bbit-dp-mp-sel"); 
} 
else { 
$(ms[i]).removeClass("bbit-dp-mp-sel"); 
} 
} 
rryear(y); 
mp.css("top", -193).show().animate({ top: 0 }, { duration: 200 }); 
} 
function getTd(elm) { 
if (elm.tagName.toUpperCase() == "TD") { 
return elm; 
} 
else if (elm.tagName.toUpperCase() == "BODY") { 
return null; 
} 
else { 
var p = $(elm).parent(); 
if (p.length > 0) { 
if (p[0].tagName.toUpperCase() != "TD") { 
return getTd(p[0]); 
} 
else { 
return p[0]; 
} 
} 
} 
return null; 
} 
function tbhandler(e) { 
var et = e.target || e.srcElement; 
var td = getTd(et); 
if (td == null) { 
return false; 
} 
var $td = $(td); 
if (!$(td).hasClass("bbit-dp-disabled")) { 
var s = $td.attr("xdate"); 
var arrs = s.split("-"); 
cp.data("indata", new Date(arrs[0], parseInt(arrs[1], 10) - 1, arrs[2])); 
returndate(); 
} 
return false; 
} 
function returnfalse() { 
return false; 
} 
function prevm() { 
if (def.Month == 1) { 
def.Year--; 
def.Month = 12; 
} 
else { 
def.Month-- 
} 
writecb(); 
return false; 
} 
function nextm() { 
if (def.Month == 12) { 
def.Year++; 
def.Month = 1; 
} 
else { 
def.Month++ 
} 
writecb(); 
return false; 
} 
function returntoday() { 
cp.data("indata", new Date()); 
returndate(); 
} 
function returndate() { 
var ct = cp.data("ctarget"); 
var ck = cp.data("cpk"); 
var re = cp.data("onReturn"); 
var ndate = cp.data("indata") 
var ads = cp.data("ads"); 
var ade = cp.data("ade"); 
var dis = false; 
if (ads && ndate < ads) { 
dis = true; 
} 
if (ade && ndate > ade) { 
dis = true; 
} 
if (dis) { 
return; 
} 
if (re && jQuery.isFunction(re)) { 
re.call(ct[0], cp.data("indata")); 
} 
else { 
ct.val(cp.data("indata").Format("yyyy-MM-dd")); 
} 
ck.attr("isshow", "0"); 
cp.removeData("ctarget").removeData("cpk").removeData("indata").removeData("onReturn") 
.removeData("ads").removeData("ade"); 
cp.css("visibility", "hidden"); 
ct = ck = null; 
} 
function writecb() { 
var tb = $("#BBIT_DP_INNER tbody"); 
$("#BBIT_DP_YMBTN").html(def.monthName[def.Month - 1] + def.monthp + " " + def.Year); 
var firstdate = new Date(def.Year, def.Month - 1, 1); 
var diffday = def.weekStart - firstdate.getDay(); 
var showmonth = def.Month - 1; 
if (diffday > 0) { 
diffday -= 7; 
} 
var startdate = DateAdd("d", diffday, firstdate); 
var enddate = DateAdd("d", 42, startdate); 
var ads = cp.data("ads"); 
var ade = cp.data("ade"); 
var bhm = []; 
var tds = def.today.Format("yyyy-MM-dd"); 
var indata = cp.data("indata"); 
var ins = indata != null ? indata.Format("yyyy-MM-dd") : ""; 
for (var i = 1; i <= 42; i++) { 
if (i % 7 == 1) { 
bhm.push("<tr>"); 
} 
var ndate = DateAdd("d", i - 1, startdate); 
var tdc = []; 
var dis = false; 
if (ads && ndate < ads) { 
dis = true; 
} 
if (ade && ndate > ade) { 
dis = true; 
} 
if (ndate.getMonth() < showmonth) { 
tdc.push("bbit-dp-prevday"); 
} 
else if (ndate.getMonth() > showmonth) { 
tdc.push("bbit-dp-nextday"); 
} 
if (dis) { 
tdc.push("bbit-dp-disabled"); 
} 
else { 
tdc.push("bbit-dp-active"); 
} 
var s = ndate.Format("yyyy-MM-dd"); 
if (s == tds) { 
tdc.push("bbit-dp-today"); 
} 
if (s == ins) { 
tdc.push("bbit-dp-selected"); 
} 
bhm.push("<td class='", tdc.join(" "), "' title='", ndate.Format("yyyy-MM-dd"), "' xdate='", ndate.Format("yyyy-M-d"), "'><a href='javascript:void(0);'><em><span>", ndate.getDate(), "</span></em></a></td>"); 
if (i % 7 == 0) { 
bhm.push("</tr>"); 
} 
} 
tb.html(bhm.join("")); 
} 
var dateReg = /^(\d{1,4})(-|\/|.)(\d{1,2})\2(\d{1,2})$/; 
return $(this).each(function() { 
var obj = $(this).addClass("bbit-dp-input"); 
var picker = $(def.picker); 
def.showtarget == null && obj.after(picker); 
picker.click(function(e) { 
var isshow = $(this).attr("isshow"); 
//先隐藏 
var me = $(this); 
if (cp.css("visibility") == "visible") { 
cp.css(" visibility", "hidden"); 
} 
if (isshow == "1") { 
me.attr("isshow", "0"); 
cp.removeData("ctarget").removeData("cpk").removeData("indata").removeData("onReturn"); 
return false; 
} 
var v = obj.val(); 
if (v != "") { 
v = v.match(dateReg); 
} 
if (v == null || v == "") { 
def.Year = new Date().getFullYear(); 
def.Month = new Date().getMonth() + 1; 
def.Day = new Date().getDate(); 
def.inputDate = null 
} 
else { 
def.Year = parseInt(v[1], 10); 
def.Month = parseInt(v[3], 10); 
def.Day = parseInt(v[4], 10); 
def.inputDate = new Date(def.Year, def.Month - 1, def.Day); 
} 
cp.data("ctarget", obj).data("cpk", me).data("indata", def.inputDate).data("onReturn", def.onReturn); 
if (def.applyrule && $.isFunction(def.applyrule)) { 
var rule = def.applyrule.call(obj, obj[0].id); 
if (rule) { 
if (rule.startdate) { 
cp.data("ads", rule.startdate); 
} 
else { 
cp.removeData("ads"); 
} 
if (rule.enddate) { 
cp.data("ade", rule.enddate); 
} 
else { 
cp.removeData("ade"); 
} 
} 
} 
else { 
cp.removeData("ads").removeData("ade") 
} 
writecb(); 
$("#BBIT-DP-T").height(cp.height()); 
var t = def.showtarget || obj; 
var pos = t.offset(); 
var height = t.outerHeight(); 
var newpos = { left: pos.left, top: pos.top + height }; 
var w = cp.width(); 
var h = cp.height(); 
var bw = document.documentElement.clientWidth; 
var bh = document.documentElement.clientHeight; 
if ((newpos.left + w) >= bw) { 
newpos.left = bw - w - 2; 
} 
if ((newpos.top + h) >= bh) { 
newpos.top = pos.top - h - 2; 
} 
if (newpos.left < 0) { 
newpos.left = 10; 
} 
if (newpos.top < 0) { 
newpos.top = 10; 
} 
$("#BBIT-DP-MP").hide(); 
newpos.visibility = "visible"; 
cp.css(newpos); 
//cp.show(); 
$(this).attr("isshow", "1"); 
$(document).one("click", function(e) { 
me.attr("isshow", "0"); 
cp.removeData("ctarget").removeData("cpk").removeData("indata"); 
cp.css("visibility", "hidden"); 
}); 
return false; 
}); 
}); 
}; 
})(jQuery);

那接着就是分析一下实现的主要过程和一些注意的要点:
首先还是套版化编写jQuery控件的套子:
;(function($) { 
//也可以使用$.fn.extend(datepicker:function(o){}) 
$.fn.datepicker= function(o) { 
} 
})(jQuery);

这样做的好处上篇已经讲过了 ,就不重述了
接着就是定义默认的参数,已在代码中添加了注释说明这些参数的意义,有几个参数是为了多语言而设置的,如weekName,monthName
var def = { 
weekStart: 0,//一周开始的是星期几0代表星期天 
weekName: ["日", "一", "二", "三", "四", "五", "六"], //星期的格式 
monthName: ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"], //月份的格式 
monthp: "月",//月的后缀 
Year: new Date().getFullYear(), //定义年的变量的初始值 
Month: new Date().getMonth() + 1, //定义月的变量的初始值 
Day: new Date().getDate(), //定义日的变量的初始值 
today: new Date(),//today 
btnOk: " 确定 ",//确定按钮的文字 
btnCancel: " 取消 ",//取消按钮的文字 
btnToday: "今天", //今天按钮的文字 
inputDate: null,//无用,只是在代码中会用它存放数据 
onReturn: false,//当选择日期后回调的函数 
version: "1.0",//版本 
applyrule: false, //日期选择规则,可设置可选择的日期范围function(){};return rule={startdate,endate}; 
showtarget: null, //显示载体,日历展开式所依赖的对象,默认是对象本身 
picker: "" //附加点击事件的对象 
}; 
$.extend(def, o);//用传递过来的参数来填充默认

第二部自然是初始化月视图和年月选择视图的HTML了
//给日期选择控件一个特殊的ID,获取这个ID的对象,判断如果对象存在,则直接使用 
// 日期的HTML采用单例,即一个页面上只生成一份HTML 
var cp = $("#BBIT_DP_CONTAINER"); 
if (cp.length == 0) { 
var cpHA = []; //老规矩还是用数组拼接html,最后用innerHTML的方式附加到容器,提升性能 
cpHA.push("<div id='BBIT_DP_CONTAINER' class='bbit-dp' style='width:175px;z-index:999;'>"); 
if ($.browser.msie6) { //如果是IE6弹出层遮盖select 
cpHA.push('<iframe style="position:absolute;z-index:-1;width:100%;height:100%;top:0;left:0;scrolling:no;" frameborder="0" src="about:blank"></iframe>'); 
} 
cpHA.push("<table class='dp-maintable' cellspacing='0' cellpadding='0' style='width:175px;'><tbody><tr><td>"); 
//头哟 
cpHA.push("<table class='bbit-dp-top' cellspacing='0'><tr><td class='bbit-dp-top-left'> <a id='BBIT_DP_LEFTBTN' href='javascript:void(0);' title='向前一个月'> </a></td><td class='bbit-dp-top-center' align='center'><em><button id='BBIT_DP_YMBTN'>九月 2009</button></em></td><td class='bbit-dp-top-right'><a id='BBIT_DP_RIGHTBTN' href='javascript:void(0);' title='向后一个月'> </a></td></tr></table>"); 
cpHA.push("</td></tr>"); 
cpHA.push("<tr><td>"); 
//周 
cpHA.push("<table id='BBIT_DP_INNER' class='bbit-dp-inner' cellspacing='0'><thead><tr>"); 
//生成周 
for (var i = def.weekStart, j = 0; j < 7; j++) { 
cpHA.push("<th><span>", def.weekName[i], "</span></th>"); 
if (i == 6) { i = 0; } else { i++; } 
} 
.....//省略若干代码 
cpHA.push("</tbody></table>"); 
cpHA.push("</div>"); 
cpHA.push("</div>"); 
var s = cpHA.join(""); 
$(document.body).append(s); //添加到body中 
cp = $("#BBIT_DP_CONTAINER"); //再获取一遍 
initevents(); //初始化事件 
}

这里有一个关键点,就是日期的html输出和事件初始化只做一次,因为基本上一页上同时不会打开两个。还有就是生成html中有一些特殊的自定义属性哦,仔细看下就会发现的,这些属性在后面的时间处理中都有很大的作用。那么来看一下事件吧
$("#BBIT-DP-TODAY").click(returntoday);//今天按钮的事件 
cp.click(returnfalse);//阻止冒泡 
$("#BBIT_DP_INNER tbody").click(tbhandler);//给月视图中间body添加click事件而不是给每个td添加 
$("#BBIT_DP_LEFTBTN").click(prevm);//上个月 
$("#BBIT_DP_RIGHTBTN").click(nextm);//下个月 
$("#BBIT_DP_YMBTN").click(showym);//切换到年月视图 
$("#BBIT-DP-MP").click(mpclick);//年月视图的点击事件,同样用于分发 
$("#BBIT-DP-MP-PREV").click(mpprevy);//上一年 
$("#BBIT-DP-MP-NEXT").click(mpnexty);//下一年 
$("#BBIT-DP-MP-OKBTN").click(mpok);//ok按钮的事件 
$("#BBIT-DP-MP-CANCELBTN").click(mpcancel);//cancel按钮的事件

给每一个需要点击的元素加上事件哦,这里有两个地方比较特殊,一个事月视图的点击视图,传统的做法就是给每个td都加事件,但是这个时候我的td还没有呢,但是如果在每次生成td的时候来附加事件,那么就由影响性能,所以直接给容器加了click事件,通过对事件源的判断来分发事件,另外一个年月选择视图,也是和上面一样的逻辑,那么我们
就拿月视图的点击事件来分析一下,其实每一个td生成的时候都会注册一个xdate自定义属性

,来看一下tbhandler函数
function tbhandler(e) { 
var et = e.target || e.srcElement; //找到事件源 
var td = getTd(et); //事件源递归往上找td 
if (td == null) { 
return false; 
} 
var $td = $(td); 
. 
if (!$(td).hasClass("bbit-dp-disabled")) {如果不是禁用状态 
var s = $td.attr("xdate");//获取td的自定义属性日期数据 
var arrs = s.split("-"); 
cp.data("indata", new Date(arrs[0], parseInt(arrs[1], 10) - 1, arrs[2])); 
returndate();//返回日期 
. 
} 
return false; 
}

所有的日期选择时间初始化好了(一次性的),接着就要给每一个的picker添加点击事件了
return $(this).each(function() { 
var obj = $(this).addClass("bbit-dp-input");//给input添加样式 
var picker = $(def.picker);//获取picker对象 
//如果showtarget不为null这将picker注册到input的后面 
//否则用户自己处理picker的位置,即picker在页面上本身就已经存在 
//大家可以看看示例中1,3调用的区别 
def.showtarget == null && obj.after(picker); 
picker.click(function(e) { 
....//省略代码 
});

picker的点击事件比较长,单独拿出来讲一下我想比较好,第一个要点是现实隐藏事件的处理,第二个是窗口边缘问题的处理,还有一个就是日期范围规则的处理。
function(e) { 
//获取当前是否显示 
var isshow = $(this).attr("isshow"); 
var me = $(this); 
//如果显示着,则隐藏,用于处理点击一下picker显示,再点击picker隐藏的逻辑 
if (cp.css("visibility") == "visible") { 
cp.css(" visibility", "hidden"); 
} 
//同样是如果显示着 
if (isshow == "1") { 
me.attr("isshow", "0"); 
//remover临时数据,因为是单例所以要表示当前是哪个input 
cp.removeData("ctarget").removeData("cpk").removeData("indata").removeData("onReturn"); 
return false; //阻止冒泡 
} 
//如果隐藏着,获取input的值 
var v = obj.val(); 
if (v != "") { 
v = v.match(dateReg);//验证一下格式是否正确 
} 
if (v == null || v == "") {//格式不正确或为空则用当前日期 
def.Year = new Date().getFullYear(); 
def.Month = new Date().getMonth() + 1; 
def.Day = new Date().getDate(); 
def.inputDate = null 
} 
else { 
//否则使用input的日期 
def.Year = parseInt(v[1], 10); 
def.Month = parseInt(v[3], 10); 
def.Day = parseInt(v[4], 10); 
def.inputDate = new Date(def.Year, def.Month - 1, def.Day); 
} 
//注册临时数据 
cp.data("ctarget", obj).data("cpk", me).data("indata", def.inputDate).data("onReturn", def.onReturn); 
//调用规则,返回可选的日期范围 
if (def.applyrule && $.isFunction(def.applyrule)) { 
var rule = def.applyrule.call(obj, obj[0].id); 
if (rule) { 
if (rule.startdate) { 
cp.data("ads", rule.startdate); 
} 
else { 
cp.removeData("ads"); 
} 
if (rule.enddate) { 
cp.data("ade", rule.enddate); 
} 
else { 
cp.removeData("ade"); 
} 
} 
} 
else { 
//不存在则删除限制 
cp.removeData("ads").removeData("ade") 
} 
//画月日历内容td了 
writecb(); 
$("#BBIT-DP-T").height(cp.height()); 
//获取显示依附的对象 
var t = def.showtarget || obj; 
//获取对象的位置 
var pos = t.offset(); 
//获取对象的高度 
var height = t.outerHeight(); 
//日期选择框的位置是依附对象的位置加上本身高度 
var newpos = { left: pos.left, top: pos.top + height }; 
//以下都是处理窗口边界问题 
var w = cp.width(); 
var h = cp.height(); 
var bw = document.documentElement.clientWidth; 
var bh = document.documentElement.clientHeight; 
if ((newpos.left + w) >= bw) { 
newpos.left = bw - w - 2; 
} 
if ((newpos.top + h) >= bh) { 
newpos.top = pos.top - h - 2; 
} 
if (newpos.left < 0) { 
newpos.left = 10; 
} 
if (newpos.top < 0) { 
newpos.top = 10; 
} 
//强制默认是月日期视图 
$("#BBIT-DP-MP").hide(); 
newpos.visibility = "visible"; 
cp.css(newpos); //移动到知道位置并显示 
//cp.show(); 
$(this).attr("isshow", "1"); 
//给document注册单次的click事件,解决打开日期选择器后,点击其他位置,隐藏日期选择器的问题 
$(document).one("click", function(e) { 
me.attr("isshow", "0"); 
cp.removeData("ctarget").removeData("cpk").removeData("indata"); 
cp.css("visibility", "hidden"); 
}); 
return false;//组织冒泡 
}

其他一些代码都是日期操作的函数,如上月下月等就不做介绍了,大家如果对代码上又任何问题都可以留言,我一定解答,最后是示例了 .

第一个示例是老老实实的演示Demo示例,有三种方式,也有调用方式的说明:http://jscs.cloudapp.net/ControlsSample/dpdemo
第二个示例是我写的日程管理控件中结合datepicker的应用(大家可以先看看这个)http://xuanye.cloudapp.net/

位置是:






是datepicker在我的创造中的应用,最后如果你觉得这边文章对你有所帮助,那就点击一下【推荐】?
代码打包脚本之家
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: