2013年3月6日 星期三

【jQuery】如何讓datepicker中某些特定日期不可選?

由於最近有個案子客戶需要頁面上出現連續兩個月份的日期並且可設定特定日期不可點選,因為一直以來日曆部分我都是採用jquery ui中的datepicker,所以一聽到客戶這樣的需求就直接往jquery ui官網中查詢。

預先看線上demo請點我

過程說明如下:

首先,先載入必要的檔案:
 






jquery-ui-blitzer.css 套用jquery ui的css
jquery-1.7.2.min.js 必須先載入jquery的js檔,後續才能使用相關的jquery語法
jquery-ui.min.js 由於datepicker是jquery ui裡的工具,所以需要載入jquery ui的js檔
ui.datepicker-zh-TW.js 由於datepicker上的文字預設都是英文,若需要以中文呈現可另外載入此js檔
date_process.js 稍後關於本文效果的js





接著是html部分:
 
您選擇的日期:
設定不可選日期:

請以半形逗號「,」區隔每個不可選日期
由於datepicker目前是設定預設載入當前兩個月份,但不可選日期是設定測試當時兩個月份中的日期,
若發現不可選日期已為datepicker目前月份的過去式,可自行重新輸入不可選日期再點擊「重新設定不可選日期」即可查看該效果。


最後是主要JS部分:

Jquery ui 官網中,關於datepick最原始的初始化程式碼只需要:
 
$( "#datepicker" ).datepicker();

但若有其他額外需求可個別設定option,在這裡就不個別介紹,如果有需要請參考官網api 。

由於是關於貨物預定到達日的設定,並且若出貨日過量可讓店家將該日設定為讓user不可選擇,所以需求除了顯示連續兩個月份,並且不可換月,所以datepicker中的option設定如下:
 
$('#datepicker').datepicker({
    hideIfNoPrevNext : true, //此設定需搭配maxDate、minDate才能正常work
    maxDate          : maxD,
    minDate          : minD,
    showOtherMonths  : false,   //是否顯示其他月份   
    numberOfMonths   : 2,     //一次顯示多個月份個數
    dateFormat       : 'yy/mm/dd',
    beforeShowDay    :setDisableDate,
    onSelect : function(date,obj){
       $("#arriveDate").val(date); //將選擇日期於arriveDate欄位中顯示出來
    }
}); 

hideIfNoPrevNext 用來設定是否顯示換月的上下月按鈕,必須同時搭配maxDate、minDate才能正常work。
maxDate、minDate 由於需求為顯示當前連續兩個月份,所以必須設定此兩個option的最大最小日。
showOtherMonths 是否顯示非當月、其他月份的日期。
numberOfMonths 顯示多個月份的個數設定,由於需求為連續兩個月份,所以設定為2。
dateFormat 日期格式設定。
beforeShowDay datepicker中每個日期顯示前會呼叫此處設定的函數,此函數會帶入一個date參數,回傳值的格式為含有3個索引值的陣列,其中:
[0]:true/false,設定該日期是否可選。
[1]:字串,設定該日期的css class name,可設定空值表示使用預設css。
[2]:滑鼠滑過該日期要顯示的文字可設定於此,可不做設定。
onSelect 選擇日期後會呼叫此處的函數。

由於範例程式中,預設是抓當前連續兩個月份,但是不可選日期是直接設定測試文章當前月份的的幾個日期,為防之後再讀到本文觀看範例時會看不到不可選日期的效果,範例檔將不可選日期以textarea方式設定,所以可以自行修改textarea中的日期及時觀看效果。



以下是本次範例的詳細js內容:
 
$(document).ready(function(){
    var DisableDate = [];
 
    //初次載入預設已textarea內日期清單為DisableDate去初始化datepicker
    findDisableDate();
    findMaxMin(initDatePicker);
 
    $("#reSetDisableDate").click(function(){
        //由於datepicker呈現連續兩個月分部分目前是設計為預設顯示「當月+下月」
        //textarea內設定的不可選日期為demo當月的日期,為了之後的月份也可測試此效果
        //可修改textarea內日期重新查看效果
        findDisableDate();
        findMaxMin(initDatePicker);
    });
 
});

 function findDisableDate()
 {//將textarea內的日期清單設為var DisableDate
     DisableDate =[];
     var disableD = ($.trim($("#disableDate").val())).replace("\n","");
     //console.log(disableD);
     DisableDate = disableD.split(",");  
     //console.log(DisableDate);
 }
 
 function findMaxMin(callback)
 {//取出連續兩個月分中最後一天及第一天
     var today = new Date();
     var todayY = today.getFullYear();
     var todayM = today.getMonth(); //起始值是0,即0=1月
     var minD = new Date(todayY,todayM,1);  
     //月份+1為下一個月
     today.setMonth(todayM+1);
     var nextMY = today.getFullYear();
     var nextMM = today.getMonth();
     var nextDays = daysInMonth(nextMY,nextMM);  
     var maxD = new Date(nextMY,nextMM,nextDays); 
     callback(maxD,minD);
 }
 
 function initDatePicker(maxD,minD)
 {
     //移除原先的datepicker (一定要加入此語法,否則修改不可選日期後,無法正確的重新初始化)
     $('#datepicker').datepicker("destroy");
     //初始化datepicker
     $('#datepicker').datepicker({
         hideIfNoPrevNext : true, //此設定需搭配maxDate、minDate才能正常work
         maxDate          : maxD,
         minDate          : minD,
         showOtherMonths  : false,   //是否顯示其他月份   
         numberOfMonths   : 2,     //一次顯示多個月份個數
         dateFormat       : 'yy/mm/dd',
         beforeShowDay    :setDisableDate,
         onSelect : function(date,obj){
               $("#arriveDate").val(date); //將選擇日期於arriveDate欄位中顯示出來
         }
  }); 
 }
 
 function setDisableDate(date)
 {//getMonth的起始值是0,即0=1月,故需+1表示真實解讀的月份
     var strDate = date.getFullYear() + "/" + (date.getMonth()+1) + "/" + date.getDate()
     //console.log(strDate);
     var aryReturn =  [true,""];
     $.each(DisableDate,function(key,value){
         if ( value==strDate )
         {
             aryReturn = [false,"","此日不可選"];
         }
     }); 
     return aryReturn;
 }
 
 function daysInMonth(iYear,iMonth)
 {//取得iYear年iMonth月該月份天數
     return 32 - new Date(iYear, iMonth, 32).getDate();
 }

如果您喜歡我的分享、或是我的文章對您有幫助的話,希望能到我的粉絲專頁點個讚追蹤我唷~~

寫程式、技術分享文章很辛苦,寫一篇要花非常久的時間,希望您能幫我點一下頁面上的廣告給我支持跟肯定,讓我更有動力寫這類文章唷~

沒有留言:

張貼留言

writing for work~writing for life~