打造基于jQuery的日期选择控件
终于把jQuery拼写正确了哈,哈哈javascript也是区分大小写的,所以确实不能写错,今天我来和大家分享的是日期选择控件的实现,功能也许不够强大,但是能够满足需求。
我之前也写过(正确的说是改过一个日期选择控件,点击这里查看),看下截图哈,也很酷的,windows风格哦。
但是也有些问题,第一画日历有点慢,第二兼容性不太好IE Only,第三它不是基于jQuery的哈哈。
那还是老规矩,做之前先看下效果
这下是更酷的Ext风格了。
从上图我们可以看出这个控件其实有两个视图一个日期月视图,还有一个是年月选择视图。
1:还是先从HTML入手
日期控件确定HTML其实还是比较简单,因为明摆着是列表的数据格式,当然主要是采用table了。
两个视图分别用两个Div包裹,控制div的显示隐藏即可以切换视图了。完整的HTMl结构大家可以用IEDeveloper看一下Demo的结构,我自己截了一个图
2:根据HTML和效果图编写CSS
其实因为是Ext风格的,所以直接copy的ext的css和图片。。
CSS也就不分析了,直接上代码。
因为博客园的语法高亮不支持CSS,所以就不贴出来了,给个下载地址吧:
http://xuanye.cloudapp.net/Theme/Default/dp.css
所有用到的图片:
3:搞定了CSS之后呢,就开始编写我们javascript了。
上来就是一个完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | ;( 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控件的套子:
1 2 3 4 5 | ;( function ($) { //也可以使用$.fn.extend(datepicker:function(o){}) $.fn.datepicker= function (o) { } })(jQuery); |
这样做的好处上篇已经讲过了 ,就不重述了
接着就是定义默认的参数,已在代码中添加了注释说明这些参数的意义,有几个参数是为了多语言而设置的,如weekName,monthName
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | //给日期选择控件一个特殊的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中有一些特殊的自定义属性哦,仔细看下就会发现的,这些属性在后面的时间处理中都有很大的作用。那么来看一下事件吧
1 2 3 4 5 6 7 8 9 10 11 | $( "#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自定义属性 ,来看一下tbhandler函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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添加点击事件了
1 2 3 4 5 6 7 8 9 10 11 12 | 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的点击事件比较长,单独拿出来讲一下我想比较好,第一个要点是显示隐藏事件的处理,第二个是窗口边缘问题的处理,还有一个就是日期范围规则的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 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的应用(大家可以先看看这个)
是datepicker在我的创造中的应用,最后如果你觉得这边文章对你有所帮助,那就点击一下【推荐】?
本文的地址:http://www.cnblogs.com/xuanye/archive/2009/10/27/1590992.html
转载请保留上面的链接,谢谢
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2008-10-27 备忘:OWA中自定义URL