基于jQuery的日期选择控件


Posted in Javascript onOctober 27, 2009

但是也有些问题,第一画日历有点慢,第二兼容性不太好IE Only,第三它不是基于jQuery的哈哈。

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

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

日期控件确定HTML其实还是比较简单,因为明摆着是列表的数据格式,当然主要是采用table了。
两个视图分别用两个Div包裹,控制div的显示隐藏即可以切换视图了。完整的HTMl结构大家可以用IEDeveloper看一下Demo的结构,我自己截了一个图
基于jQuery的日期选择控件 
2:根据HTML和效果图编写CSS
其实因为是Ext风格的,所以直接copy的ext的css和图片。。
CSS也就不分析了,直接上代码。
因为博客园的语法高亮不支持CSS,所以就不贴出来了,给个下载地址吧:
所有用到的图片:

基于jQuery的日期选择控件 基于jQuery的日期选择控件 基于jQuery的日期选择控件

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='向前一个月'>&nbsp;</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='向后一个月'>&nbsp;</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='向前一个月'>&nbsp;</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='向后一个月'>&nbsp;</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自定义属性 基于jQuery的日期选择控件 ,来看一下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/

 

位置是:基于jQuery的日期选择控件基于jQuery的日期选择控件 

Javascript 相关文章推荐
用Javascript数组处理多个字符串的连接问题
Aug 20 Javascript
基于jQuery的日期选择控件
Oct 27 Javascript
JavaScript写的一个自定义弹出式对话框代码
Jan 17 Javascript
Javascript中的window.event.keyCode使用介绍
Apr 26 Javascript
jquery按回车提交数据的代码示例
Nov 05 Javascript
如何在JavaScript中实现私有属性的写类方式(一)
Dec 04 Javascript
Backbone.js中的集合详解
Jan 14 Javascript
微信小程序中顶部导航栏的实现代码
Mar 30 Javascript
js module大战
Apr 19 Javascript
Vue 动态组件components和v-once指令的实现
Aug 30 Javascript
解决vue自定义指令导致的内存泄漏问题
Aug 04 Javascript
详解vite+ts快速搭建vue3项目以及介绍相关特性
Feb 25 Vue.js
html 锁定页面(js遮罩层弹出div效果)
Oct 27 #Javascript
javascript 读取XML数据,在页面中展现、编辑、保存的实现
Oct 27 #Javascript
Ajax+Json 级联菜单实现代码
Oct 27 #Javascript
javascript 关于# 和 void的区别分析
Oct 26 #Javascript
用Greasemonkey 脚本收藏网站会员信息到本地
Oct 26 #Javascript
解决jquery .ajax 在IE下卡死问题的解决方法
Oct 26 #Javascript
解决表单中第一个非隐藏的元素获得焦点的一个方案
Oct 26 #Javascript
You might like
smarty 缓存控制前的页面静态化原理
2013/03/15 PHP
关于php循环跳出的问题
2013/07/01 PHP
php实现根据词频生成tag云的方法
2015/04/17 PHP
再谈PHP中单双引号的区别详解
2016/06/12 PHP
Yii针对添加行的增删改查操作示例
2016/10/18 PHP
Javascript attachEvent传递参数的办法
2009/12/14 Javascript
javascript 动态设置已知select的option的value值的代码
2009/12/16 Javascript
js左侧多级菜单动态的解决方案
2010/02/01 Javascript
jQuery插件开发基础简单介绍
2013/01/07 Javascript
javascript 判断整数方法分享
2014/12/16 Javascript
javascript感应鼠标图片透明度显示的方法
2015/02/24 Javascript
常用DOM整理
2015/06/16 Javascript
jQuery插入节点和移动节点用法示例(insertAfter、insertBefore方法)
2016/09/08 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
2016/12/14 Javascript
BootStrap Table前台和后台分页对JSON格式的要求
2017/06/28 Javascript
详解在vue-cli中使用路由
2017/09/25 Javascript
将jquery.qqFace.js表情转换成微信的字符码
2017/12/01 jQuery
用Node提供静态文件服务的方法
2018/07/06 Javascript
Vue路由钩子之afterEach beforeEach的区别详解
2018/07/15 Javascript
JSONP原理及应用实例详解
2018/09/13 Javascript
layui文件上传控件带更改后数据传值的方法
2019/09/23 Javascript
js+cavans实现图片滑块验证
2020/09/29 Javascript
uni-app 自定义底部导航栏的实现
2020/12/11 Javascript
js实现有趣的倒计时效果
2021/01/19 Javascript
python连接MySQL、MongoDB、Redis、memcache等数据库的方法
2013/11/15 Python
python去除扩展名的实例讲解
2018/04/23 Python
python 实时得到cpu和内存的使用情况方法
2018/06/11 Python
python中if及if-else如何使用
2020/06/02 Python
Pytorch学习之torch用法----比较操作(Comparison Ops)
2020/06/28 Python
美国受欢迎的眼影品牌:BH Cosmetics
2016/10/25 全球购物
学生手册家长评语
2014/02/10 职场文书
租车协议书范本
2014/04/22 职场文书
关于读书的演讲稿600字
2014/08/27 职场文书
公务员年终个人总结
2015/02/12 职场文书
烈士陵园扫墓感想
2015/08/07 职场文书
宝宝满月宴答谢词
2015/09/30 职场文书