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;
}