zoukankan      html  css  js  c++  java
  • 打造基于jQuery的日期选择控件

    终于把jQuery拼写正确了哈,哈哈javascript也是区分大小写的,所以确实不能写错,今天我来和大家分享的是日期选择控件的实现,功能也许不够强大,但是能够满足需求。

    我之前也写过(正确的说是改过一个日期选择控件,点击这里查看),看下截图哈,也很酷的,windows风格哦。

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

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

    image  image

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

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

    2:根据HTML和效果图编写CSS

    其实因为是Ext风格的,所以直接copy的ext的css和图片。。

    CSS也就不分析了,直接上代码。

    因为博客园的语法高亮不支持CSS,所以就不贴出来了,给个下载地址吧:

     http://xuanye.cloudapp.net/Theme/Default/dp.css

    所有用到的图片:

    btn-arrow btn-arrow-light cal

    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='175px;z-index:999;'>");
                if ($.browser.msie6) {
                    cpHA.push('<iframe style="position:absolute;z-index:-1;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='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=' 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='175px;z-index:999;'>");
                if ($.browser.msie6) { //如果是IE6弹出层遮盖select
                    cpHA.push('<iframe style="position:absolute;z-index:-1;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='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的时候来附加事件,那么就由影响性能,所以直接给容器加了点击事件,通过对事件源的判断来分发事件,另外一个年月选择视图,也是和上面一样的逻辑,那么我们就拿月视图的点击事件来分析一下,其实每一个td生成的时候都会注册一个xdate自定义属性 image ,来看一下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); //移动到对应位置并显示
    
                     $(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/

    位置是:imageimage 

    是datepicker在我的创造中的应用,最后如果你觉得这边文章对你有所帮助,那就点击一下【推荐】?

    本文的地址:http://www.cnblogs.com/xuanye/archive/2009/10/27/1590992.html

    转载请保留上面的链接,谢谢

  • 相关阅读:
    金蝶 kis一些功能的内部逻辑和个人技巧
    mysql横向和纵向合并sql数据用于展示,快递导出导入海量数据
    laravel carbon时间处理组件开发文档-中文版
    金蝶kis数据库说明(转载)
    java微信支付,对账单下载
    RabbitMQ中文文档PHP版本(七)--发布者确认
    RabbitMQ中文文档PHP版本(六)--远程过程调用(RPC)
    RabbitMQ中文文档PHP版本(五)--主题
    RabbitMQ中文文档PHP版本(四)--路由
    RabbitMQ中文文档PHP版本(二)--发布/订阅
  • 原文地址:https://www.cnblogs.com/xuanye/p/1590992.html
Copyright © 2011-2022 走看看