旅游頻道的開發中需要定義各種日期組件,有的是基本的日期選擇,
這個基本日期只包含如下功能
- 左右翻(月)
- 點擊天回填到輸入域
- 點擊“今天”,回填今天的日期到輸入域
- 點擊“關閉”,日期控件關閉
有的同時顯示兩個月的日期
有的包含一些業務信息,比如機票搜索結果頁的低價日歷。
這個比上面的要復雜一些
- 每天的日期格子里含有價格信息
- 點擊左右箭頭會向后退請求更新每天的低價機票信息
- 且點擊每天的格子是會重新查詢
這里記錄下一個基本日歷組件的要點
一、HTML結構
這里以table來布局,由以下三個部分組成
分別對應,thead(顯示區,左右箭頭切換月份),tbody(顯示天,點擊天回填到輸入域),tfoot(補充工具區)
開發日期組件之前就有個疑問,為什么星期是以周日開始,而不是周一呢?細心的同學會發現很多日期組件都是以“周日”開始,比如windows和mac系統自帶的日歷
這個其實是由於日期對象的getDay方法返回的值是這樣的,這樣實現起來方便一些,當然也可以實現為從周一開始排列的。
周日 0
周一 1
周二 2
周三 3
...
順便提下 getMonth方法,它返回月份,值是從0開始的,比如
一月 0
二月 1
三月 2
...
二、核心函數
1. isLeapYear 判斷閏年
function isLeapYear(year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) }
閏年是比普通年份多出一段時間的年份,在各種歷法中都有出現,目的是為了彌補人為規定的紀年與地球公轉產生的差異。有兩個條件
a. 非整百年:年數除以4余數為1是閏年,即公元前1、5、9……年。
b. 整百年:年數除以400余數為1是閏年,年數除以3200余數為1,不是閏年,年數除以172800余1又為閏年,即公元前401、801……年。
2. calculateDays 根據年月計算天
var months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] function calculateDays(year, month) { var days = months[month] // 2月比較特殊,非閏年28天,閏年29天,如2008年2月為29天 if ( 1 == month && isLeapYear(year) ) { days = 29 } return days }
1-12月的天數分別是31,28,31,30,31,30,31,31,30,31,30,31。2月比較特殊,閏年是29天。
3. format 格式化回填到輸入框的字符串,可以帶星期,也可以不帶
4. setPosi 用來定位日期彈層的位置,一般是固定在輸入框的下面
5. onBodyClick 點擊body時的響應函數,這時會把日期彈層關閉(從DOM里刪除)
6. template 日期組件的html模板函數,生成基本的框架,但日期數據是后續回填
7. render 渲染日期組件。點擊輸入框時會調用該方法,根據當前日期生成模板,根據年月生成該月的日期天數然后回填,添加組件上各種事件,計算組件的位置后插入到body里。
8. fillDate 根據年月計算該月的天數,然后插入。比如點擊左右箭頭(上月,下月)都會調用該方法。
9. events 方法會采用事件代理機制為日歷上所有事件添加事件響應函數。即日期組件的行為由它完成。
10. prevMonth/nextMonth 是點擊左右箭頭的時候調用的,即更換月份的事件。
11. remove 將日期組件刪除,點擊body,點“關閉”,選擇一個“天” 后都會調用該方法。該方法會從DOM中把日期組件刪除,會把當前的天回填到輸入框。注意,除了從DOM節點中刪除,日期組件上的所有的事件綁定也將解除。
總結:基本上可以按照此思路來實現各種日期控件,比如有的需要添加農歷信息、節假日、有的需要添加機票的價格信息。
DEMO:http://snandy.github.io/lib/calendar/