[javascript]簡單 方便 易折騰的日歷控件,純javascript支持鏈式語法,核心代碼只有5行


又重復造了個輪子,重復造輪子當然要有優點要不就沒有存在價值。使用簡單,方便。只要5行代碼就可生成年歷。

input date已經是一個原生控件opera和chrome已經支持,日歷控件邏輯比較復雜,要做到盡善盡美也是不容易的,也是比較鍛煉編碼的,所以學習意義大於實際意義。而且這個控件也是多年心願,最近有時間寫寫停停,終於堅持下來就拿來和大家分享了。

 

 

傳送門

 

特點

1.此日歷插件特點在於簡單易用,要保證功能實現最低要求一個參數。

2.個性化配置有強大的自定義事件和多個個性化參數可選。

3.采用原型繼承,擴展派生非常方便。

4.跨瀏覽器,保證可用性。

5.采用表格做載體,無樣式也可以正常使用功能。

6.緩存,已生成月份數據。使數據持久化,減少計算。

7.無樣式支持,功能依然健在。

應用展示

a.

b.

c.

 

技術總結

1.主要難點不是日期算法,而是select控件和表格所帶來的問題。select和表格都有一套自己的dom api,來操作和訪問。尤其是生成日歷table的算法非了一些時間,而且ie瀏覽器上。innerHTML屬性,table tbody tfoot tr都是只讀的,所以對技術選型有一些干擾。中間使用了insertRow這樣的方法未果,采用分辨瀏覽器采用不同方案也行不通后,過段采用整個table都用拼字符串的方式。雖然效率不一定比生成dom節點存入變量修改高,但是結果卻是最好的。

2.select主要問題在於序號和長度差,要訪問selectedIndex,設置select的值都要小心這個變化。

3.Date對象的序號問題,年 日都是從1開始,月份是從0開始,這些差別和人類習慣的處理帶來一定成本。

可見初期,技術儲備和技術選型的重要性。

其實日期核心算法只有5行代碼而已,想要生成一個可用的日期控件20行內代碼足夠,由於和日期控件相關的控件出來帶來了大量代碼。

 

核心代碼

 

1。計算某個月有多少天,2012.6月到底有多少天呢?我們要是知道6月最后一天是多少號,不就知道6月有多少天了嗎。

new Date('2012,6,0').getDate();最簡單最短 //chrome不支持用字符串new Date('2012,6,0')格式創建日期, 但支持new Date('2012','6','0');這點要注意 而safari沒有問題非常詭異

通用的

(new Date(+(new Date(2012, 7, 1)) - 86400000)).getDate();

下個月的一號減去一天,就是當月最后一天

 

2.知道了當月有多少天還不行,要知道當月1號是要放在什么位置,如果知道1號是星期幾不就可以知道1號在什么位置了嗎。

new Date(2012, 7,1).getDay();

 

3.生成一個月的日歷,代碼很簡單只有5行

for (var i = 0; i < row; i++) {
  html.push('</tr>');
   for (var j = 0; j < 7; j++) {
      html.push((cell-- <= offset && days > 0) ? ('<td ' + (that.Date > new Date(y, m, days + 1) ? 'class="oldDay"' : '') + (y === that.Year && m === that.Month && days === that.Day ? 'class="currentDay"' : '') + ' title="'+y+that.style+(m+1)+that.style+days+'">' + (days--) + '</td>') : '<td></td>');
   }
   html.push('<tr>');
}

大家可能要懷疑為什么先寫的是 </tr>結束標簽,開始生成日歷的時候采用的是倒序循環,用li標簽,后面發現無樣式時不能使用,所以改用table但這一方式保留下來,日期也是按照從后往前生成的。然后調用數組的reverse反向join就正序了。

 

4.一個實例的6月份數據和另外一個實例的6月份數據有不同點么,或者重復使用6月份數據需要每次都計算么,答案顯然不是。相同月份的數據多次使用要是只計算一次的話就可以大大提高效率,減少計算次數。

那么這就牽扯到數據持久化的問題,怎樣把數據持久化呢或者暫時持久化?答案是把數據保存在類的屬性上隨用隨拿。

 

var key = '_date_:' + Y + ':' + M;
indicotar.cache[key] || (indicotar.cache[key] = that.getDateString(Y, M));

按照年月生成一個key,如果沒有數據就調用方法生成數據存入對應key的value。以后只用只用取出,合並字符串即可。

 

 

API

constructor:Cal(可以自行修改無依賴);
實例化:new Cal(document.body);
返回值:實例對象;
參數
Node *htmlNode nodeType為1的節點,控件會被append此節點內
Object O 配置控件可選參數
Number O.Y 設置的年份,默認當年,范圍(1970-當年+10)
Number O.M 設置的月份,默認當月,范圍(1-12)
String O.hasTitle 是否有日期控制欄,默認有'true'
String O.hasFoot 是否有腳注用來顯示年月,默認無'false'
String O.style 日期分隔符,默認'-'
Number O.startYear 開始年,默認2006
Number O.endtYear 結束年,默認當年加10
Function O.ongetdate 用戶點擊日期單元格時觸發,this指向實例,第一個參數為日期對應數組
Function O.onrender 控件插入值dom樹時觸發,this指向實例,第一個參數為控件對應的dom節點
Function O.ongetdatestring 獲得月份所對應的日期字符串時觸發,this指向實例,第一個參數為字符串
Function O.oncalframe 組成完畢控件node框架時觸發,this指向實例,第一個參數為對應的dom節點
Function fn 類的回調函數,生成控件后觸發

 

實例方法
方法名 參數 返回值
createDay Y:number/string(2012),M:number/string(0-11) 實例(1儲存日期字符串至Cal的cache中,是數據持久化;2調用render)
render node:(this.elems),key:string('_date_:2012:0'),Y:number(2012),M:number(0-11) 實例(渲染控件至dom樹)
getDateString Y:number(2012),M:number(0-11) htmlString
toString   string '2012-12-12' (獲取選中日期對應的字符串)
valueOf   Array [2012,12,12] (獲取選中日期對應的數組)
hide   實例 (隱藏控件)
show   實例 (顯示控件)
setCss Object({'font-size':'12px','width':'300px'}) 實例 (為控件添加樣式)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM