jQuery UI Datepicker改造大作戰
主題 |
jQuery UI Datepicker改造大作戰 |
文章簡介 |
利用jQuery UI Datepicker現有的功能進行改造。讓日曆選單可跨月顯示選取日期範圍區間,並隱藏其他不可選擇之日期。 |
作者 |
廖汶彬 |
版本 |
1.0 |
產出日期 |
2016.10.21 |
某天有個朋友兼同事跟我許了一個願望
網頁想要一個日期選擇器
"只要"顯示包含今天在內的當週,以及後續4周
也就是只能選取特定區間的日期
我馬上就聯想到jQuery UI的Datepicker"應該"能夠符合這樣的需要
jQuery UI Datepicker可透過設定定義可選取的日期區間
jQuery UI Datepicker Restrict the range程式碼
$( "#datepicker" ).datepicker({
minDate: 0,
maxDate: 28
});
CodePen-jQueryUI Datepicker Restrict the range
但是事情沒有我想的這麼容易
針對畫面呈現的部份還希望可以選取的日期以外的日期通通不要出現在日曆選單上
並且當日期區間未跨月則顯示1個月的日曆選單
如果跨月時要一次顯示2個月的日曆選單
由於需要去異動日曆選單的介面
所以需要在日曆選單顯示後增加程式碼去調整介面
但是jQuery UI Datepicker沒有提供這樣的事件可以使用
第一個要解決的問題是Datepicker並沒有日曆選單顯示後的事件
增加jQuery UI Datepicker日曆選單顯示後的事件(afterShow)
$.datepicker._updateDatepicker_original = $.datepicker._updateDatepicker;
$.datepicker._updateDatepicker = function(inst) {
$.datepicker._updateDatepicker_original(inst);
var afterShow = this._get(inst, 'afterShow');
if (afterShow)
afterShow.apply((inst.input ? inst.input[0] : null));
};
增加上述的程式碼之後即可在datapicker綁定時增加 afterShow 的事件設定
此外跨月時要要顯示2個月的日曆選單則可透過原本Datepicker的設定達成
numberOfMonths屬性資料類型為Number
一次顯示2個月的日曆屬性 numberOfMonths
.ui-datepicker-multi .ui-datepicker-group{
clear:both;
width:100%;
}
考慮到程式的共用性我設計了一個function用來綁定jQuery UI Datepicker
以現在的日期做基準加上minDiffDay做為可選取日期範圍的最小日期
加上maxOffsetDay做為可選取日期範圍的最大日期
並將jQuery UI Datepicker綁定至datepickerObject
此function需提供3個參數
minDiffDay:設定可選取日期範圍最小日期(單位為天,可為正負整數)
maxOffsetDay:設定可選取日期範圍最大日期(單位為天,可為正負整數)
datepickerObject:綁定目標(jQuery object)
為了方便計算日期引用了強大的時間處理的函式庫 Moment.js
計算日期區間跨了幾個月份可使用來設定numberOfMonths屬性
由於一次會顯示所有可選擇的日期區間所以就把切換月份的按鈕隱藏
屬性為hideIfNoPrevNext設定為true
設定afterShow的事件應執行的function對日曆選單的介面進行調整即可完成設定
綁定jQuery UI Datepicker的function
function RangeDatePickerBind(minDiffDay,maxOffsetDay,datepickerObject){
var minDay = new moment().add(minDiffDay, 'days');
var maxDay = new moment().add(maxOffsetDay, 'days');
var displayMonth=maxDay.month()-minDay.month()+1;
datepickerObject.datepicker({
dateFormat: "yy-mm-dd",
minDate: minDiffDay,
maxDate: maxOffsetDay,
numberOfMonths: displayMonth,
hideIfNoPrevNext: true,
afterShow:function(){
//判斷是否有自訂樣式 讓日曆選單垂直排列
if($(".ui-datepicker-multi .ui-datepicker-group").css("clear") === "both"){
$("#ui-datepicker-div").css("width",$("#ui-datepicker-div").width()/displayMonth);
}
//隱藏第一個月份可選取日期前的所有日期
$("#ui-datepicker-div .ui-datepicker-calendar:first").find("td[data-handler='selectDay']:first")
.prevAll("td").css("visibility","hidden");
$("#ui-datepicker-div .ui-datepicker-calendar:first").find("td[data-handler='selectDay']:first")
.parent("tr").prevAll("tr").find("td").hide();
//隱藏最後一個月份可選取日期後的所有日期
$("#ui-datepicker-div .ui-datepicker-calendar:last").find("td[data-handler='selectDay']:last")
.nextAll("td").hide();
$("#ui-datepicker-div .ui-datepicker-calendar:last").find("td[data-handler='selectDay']:last")
.parent("tr").nextAll("tr").find("td").hide();
}
});
}
依據需要的日期範圍與綁定目標設定完畢
即可套用這個客製化的Datepicker
使用方式
$(function() {
RangeDatePickerBind(-7,7,$("#datepicker_1"));
RangeDatePickerBind(0,28,$("#datepicker_2"));
});
以上是我改造Datepicker的過程與想法
提供給大家參考