Ooops! Have no EN version right now...
简单日期选择器 - html, js & css
一直用着现成的日期选择器?
到底这东西是怎么出来的?
动手写一个!放下所有的现成!
简单的日期选择器,只用简单的web技术
语言版本: 中
发布日期:2015-03-06
更新日期:2015-03-06
作者:lngost
URL
1. 开始前的准备
* 简单的web技术其实并不简单,只是前人已经做好了关键部分,所以有效利用吧!
* Javascript Date 对象 是实现日期选择器的关键
方法 | 描述 |
Date() | 返回当日的日期和时间 |
getFullYear() | 获取四位数年份,例如2015 |
getMonth() | 获取月份(0~11) |
getDate() | 获取某一天(1~31) |
getDay() | 获取星期数(0~6,0代表星期天) |
(完整表格参见 W3CSchool CN)
* 兼容性问题:
(1) js方面全兼容,因为对于鼠标事件的响应,采用了html标签里的onclick属性,并未采用addEventListener;
(2) css方面,只有2处需注意:box-shadow 支持IE9+;border-spacing 在定义了 !DOCTYPE 后支持 IE8+;
2. 成品演示
3. 开始吧!
(a) 写出对应的html
// html (final version) - by lngost <div id="Calendar"> <div id="Calendar-head"> <table> <tr> <td id="Calendar-year"></td> <td id="Calendar-month"></td> </tr> </table> </div> <div id="Calendar-body"> <table id="Calendar-table"></table> </div> <div id="Calendar-tail"> <div id="tip1"></div> <div id="tip2" onclick="resetToToday();">Today</div> </div> </div> <div id="input-holder"> <input type="text" name="datePicker" id="Calendar-date-input" size="25" maxlength="10" value="YYYY/MM/DD" readonly/> </div>
* 除了下方的"Today"部分,其余均使用js生成,主要是因为具体日期是需要根据用户选择而动态生成的。
(b) js部分逐步解析
- step:1
// javascript - by lngost /* Step:1 函数 Calendar() 是核心部分,主要包含了: (1)当前日期的获取:myDate = new Date(); (2)年份与月份的全局变量:yearOnShow & monthOnShow (3)一些id选择器,例如 calendarYear, 通过使用 innerHTML 来改变显示的内容 (4)用来显示年、月、日的函数: displayYear(); displayMonth(); displayCalendarTable(yearOnShow, monthOnShow - 1); 注:将显示年、月、日的代码分别封装入3个函数的目的, 是为了当用户改变年份和月份时,该部分代码可以通过函数直接调用, 提高代码复用率。 */ function Calendar() { /* init */ thead = "<tr>\ <th>Mon</th>\ <th>Tue</th>\ <th>Wed</th>\ <th>Thu</th>\ <th>Fri</th>\ <th>Sat</th>\ <th>Sun</th>\ </tr>"; myDate = new Date(); // get current date yearOnShow = myDate.getFullYear(); // year displayed on calendar monthOnShow = myDate.getMonth() + 1; // month displayed on calendar /* id selector */ calendarYear = document.getElementById("Calendar-year"); calendarMonth = document.getElementById("Calendar-month"); calendarTable = document.getElementById("Calendar-table"); calendarDateInput = document.getElementById("Calendar-date-input"); /* display current Year and Month */ displayYear(); displayMonth(); /* display calendar table */ displayCalendarTable(yearOnShow, monthOnShow - 1); } // end of Calendar()
- step:2
// javascript - by lngost /* Step:2 分别写出显示年、月、日的函数: (1)displayYear(); 显示年份的同时,加上左右2个箭头用来调整年份; 并添加鼠标点击事件:onclick='preYear();' 和 onclick='nextYear();' (2)displayMonth(); 基本同上,显示月份的同时,加上箭头用来调整月份; 不满2位数的月份前,加"0"补足。 (3)displayCalendarTable(fullYear, month); 稍显复杂的部分,若了解原理,代码就很容易了; 原理如下: * 首先考虑日历可能产生的变化情况 (规定第一行至少有一天是属于本月的) 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 或者是 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 又或者是 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 又或者是 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 以上四种,差不多是所有的极端情况了,可以看出,最少占用4行,最多占用6行; 其余的所有情况,都会介于4~6行之间。 因此,这里我们选取固定的6行,多出来的日期格子,我们可以让其显示相邻月份的日期。 (这么做的好处,就是写一个for的6次循环就可以了) * 接着,计算出该月的1号所对应的是星期几,由于我们规定1号肯定是在第一行的, 所以开头第一行第一列的对应的日期,也就不难出来了。 注:比如设定了一个临时Date实例,var temp = new Date(2015, 3, 1),也就是2015年4月1日; 当运行了 temp.setDate(temp.getDate() - 1) 之后,temp里的日期会自动变为2015年3月31日,十分智能。 * 最后,需注意星期数排布的不同所带来的影响 Sun Mon Tue Wed Thu Fri Sat 和 Mon Tue Wed Thu Fri Sat Sun 在编程时也是需要注意的,因为getDay()里,0代表Sun */ function displayYear() { calendarYear.innerHTML = "<span id='Calendar-year-pre' onclick='preYear();'><</span> " + yearOnShow + " <span id='Calendar-year-next' onclick='nextYear();'>></span>"; } function displayMonth() { var temp = "<span id='Calendar-month-pre' onclick='preMonth();'><</span> "; if (monthOnShow < 10) { temp += "0" + monthOnShow; } else { temp += monthOnShow; } temp += " <span id='Calendar-month-next' onclick='nextMonth();'>></span>"; calendarMonth.innerHTML = temp; } function displayCalendarTable(fullYear, month) { /* calculate the date of the first day on calendar table */ var temp = new Date(fullYear, month, 1); var dayOnFirst = temp.getDay(); if (dayOnFirst === 0) { dayOnFirst = 7; } temp.setDate(temp.getDate() - dayOnFirst + 1); /* count date */ tbody = ""; for (i = 0; i < 6; i++) { tbody += "<tr>"; for (j = 1; j < 8; j++) { if (temp.getFullYear() === myDate.getFullYear() && temp.getMonth() === myDate.getMonth() && temp.getDate() === myDate.getDate() && yearOnShow === myDate.getFullYear() && monthOnShow - 1 === myDate.getMonth()) { tbody += "<td class='today' onclick='chooseDate(" + temp.getDate() + ");'>" + temp.getDate() + "</td>"; } else if (temp.getMonth() === month) { tbody += "<td class='thisMonth' onclick='chooseDate(" + temp.getDate() + ");'>" + temp.getDate() + "</td>"; } else { tbody += "<td class='otherMonth'>" + temp.getDate() + "</td>"; } temp.setDate(temp.getDate() + 1); } tbody += "</tr>"; } /* display calendar table */ calendarTable.innerHTML = thead + tbody; }
- step:3
// javascript - by lngost /* Step:3 完善一些鼠标点击事件的函数: preYear();前一年 nextYear();后一年 preMonth();前一个月 nextMonth();后一个月 resetToToday();返回到今天 chooseDate(date);在 <input> 里显示选中的日期 */ function preYear() { yearOnShow--; displayYear(); displayCalendarTable(yearOnShow, monthOnShow - 1); } function nextYear() { yearOnShow++; displayYear(); displayCalendarTable(yearOnShow, monthOnShow - 1); } function preMonth() { monthOnShow--; if (monthOnShow < 1) { yearOnShow--; monthOnShow = 12; displayYear(); } displayMonth(); displayCalendarTable(yearOnShow, monthOnShow - 1); } function nextMonth() { monthOnShow++; if (monthOnShow > 12) { yearOnShow++; monthOnShow = 1; displayYear(); } displayMonth(); displayCalendarTable(yearOnShow, monthOnShow - 1); } function resetToToday() { yearOnShow = myDate.getFullYear(); monthOnShow = myDate.getMonth() + 1; displayYear(); displayMonth(); displayCalendarTable(yearOnShow, monthOnShow - 1); } function chooseDate(date) { var dd; if (date < 10) { dd = "0" + date; } else { dd = date; } var mm; if (monthOnShow < 10) { mm = "0" + monthOnShow; } else { mm = monthOnShow; } calendarDateInput.value = yearOnShow + "/" + mm + "/" + dd; }
- step:4
// javascript - by lngost /* Step:4 别忘了加上 window.onload */ window.onload = function() { Calendar(); };
(c) css部分
* 这部分讲解起来就麻烦了,毕竟也不是一两个div就解决的东西。。。
* 以下是我的源代码
// css - by lngost html, body { margin: 0; padding: 0; } #Calendar { width: 320px; box-shadow: 5px 8px 8px #D0D0D0; background: #F0F0F0; border-style: solid; border-width: 1px; border-color: #F0F0F0; } #Calendar-head table { width: 100%; text-align: center; font-size: 20px; margin: 15px auto 5px; } #Calendar-year-pre:hover, #Calendar-year-next:hover, #Calendar-month-pre:hover, #Calendar-month-next:hover { cursor: pointer; } #Calendar-table { width: 100%; table-layout: fixed; padding: 0 10px 5px; border-spacing: 5px; } #Calendar-table th { text-align: right; height: 20px; } #Calendar-table td { text-align: right; height: 30px; padding-right: 6px; } .today { color: #FFFFFF; background: #FF6633; } .today:hover { cursor: pointer; } .thisMonth { color: #000000; background: #33FF33; } .thisMonth:hover { cursor: pointer; background: #FFFF00; } .otherMonth { color: #C8C8C8; background: #FFFFFF; } #Calendar-tail { width: 100%; height: 50px; } #tip1 { background: #FF6633; width: 30px; height: 30px; margin-left: 20px; float: left; } #tip2 { width: 50px; line-height: 30px; float: left; margin-left: 8px; } #tip2:hover { cursor: pointer; } #input-holder { margin-top: 20px; } #input-holder input { font-size: 24px; }