2013-04-18 262 views
12

我使用jquery ui創建了一個日期範圍選擇器,您可以使用相同的行內日曆來進行日期選擇。jquery ui datepicker上的日期範圍選擇器

見我的小提琴這裏:http://jsfiddle.net/kVsbq/4/

JS

$(".datepicker").datepicker({ 
    minDate: 0, 
    numberOfMonths: [12, 1], 
    beforeShowDay: function (date) { 
     var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val()); 
     var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val()); 
     return [true, date1 && ((date.getTime() == date1.getTime()) || (date2 && date >= date1 && date <= date2)) ? "dp-highlight" : ""]; 
    }, 
    onSelect: function (dateText, inst) { 
     var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val()); 
     var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val()); 
     if (!date1 || date2) { 
      $("#input1").val(dateText); 
      $("#input2").val(""); 
      $(this).datepicker(); 
     } else { 
      $("#input2").val(dateText); 
      $(this).datepicker(); 
     } 
    } 
}); 

我希望能夠做的是一個範圍選擇像這樣:http://jsfiddle.net/D3wLX/1/

如果選擇一個較早的日期,則較早的日期會自動作爲範圍中的第一個日期,並突出顯示中間日期。現在在我原來的jquery ui解決方案中,它會將更早的日期放在第二個輸入中,而不是突出顯示中間的日期。

回答

6

我找到了答案在這裏:

http://www.benknowscode.com/2012/11/selecting-ranges-jquery-ui-datepicker.html

偉大的教程

$.datepicker._defaults.onAfterUpdate = null; 
 
var datepicker__updateDatepicker = $.datepicker._updateDatepicker; 
 
$.datepicker._updateDatepicker = function(inst) { 
 
    datepicker__updateDatepicker.call(this, inst); 
 
    var onAfterUpdate = this._get(inst, 'onAfterUpdate'); 
 
    if (onAfterUpdate) 
 
     onAfterUpdate.apply((inst.input ? inst.input[0] : null), 
 
     [(inst.input ? inst.input.val() : ''), inst]); 
 
} 
 
$(function() { 
 
    var cur = -1, prv = -1; 
 
    $('#jrange div') 
 
     .datepicker({ 
 
      //numberOfMonths: 3, 
 
      changeMonth: true, 
 
      changeYear: true, 
 
      showButtonPanel: true, 
 
      beforeShowDay: function (date) { 
 
        return [true, ((date.getTime() >= Math.min(prv, cur) && date.getTime() <= Math.max(prv, cur)) ? 'date-range-selected' : '')]; 
 
       }, 
 
      onSelect: function (dateText, inst) { 
 
        var d1, d2; 
 
        prv = cur; 
 
        cur = (new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)).getTime(); 
 
        if (prv == -1 || prv == cur) { 
 
        prv = cur; 
 
        $('#jrange input').val(dateText); 
 
        } else { 
 
        d1 = $.datepicker.formatDate('mm/dd/yy', new Date(Math.min(prv,cur)), {}); 
 
        d2 = $.datepicker.formatDate('mm/dd/yy', new Date(Math.max(prv,cur)), {}); 
 
        $('#jrange input').val(d1+' - '+d2); 
 
        } 
 
       }, 
 
      onChangeMonthYear: function (year, month, inst) { 
 
        //prv = cur = -1; 
 
       }, 
 
      onAfterUpdate: function (inst) { 
 
        $('<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">Done</button>') 
 
        .appendTo($('#jrange div .ui-datepicker-buttonpane')) 
 
        .on('click', function() { $('#jrange div').hide(); }); 
 
       } 
 
     }) 
 
     .position({ 
 
      my: 'left top', 
 
      at: 'left bottom', 
 
      of: $('#jrange input') 
 
     }) 
 
     .hide(); 
 
    $('#jrange input').on('focus', function (e) { 
 
     var v = this.value, 
 
      d; 
 
     try { 
 
      if (v.indexOf(' - ') > -1) { 
 
       d = v.split(' - '); 
 
       prv = $.datepicker.parseDate('mm/dd/yy', d[0]).getTime(); 
 
       cur = $.datepicker.parseDate('mm/dd/yy', d[1]).getTime(); 
 
      } else if (v.length > 0) { 
 
       prv = cur = $.datepicker.parseDate('mm/dd/yy', v).getTime(); 
 
      } 
 
     } catch (e) { 
 
      cur = prv = -1; 
 
     } 
 
     if (cur > -1) 
 
      $('#jrange div').datepicker('setDate', new Date(cur)); 
 
     $('#jrange div').datepicker('refresh').show(); 
 
     }); 
 
});
.wrapper { 
 
    height: 600px; 
 
} 
 
#jrange input { 
 
    width: 200px; 
 
} 
 
#jrange div { 
 
    font-size: 9pt; 
 
} 
 
.date-range-selected > .ui-state-active, 
 
.date-range-selected > .ui-state-default { 
 
    background: none; 
 
    background-color: lightsteelblue; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> 
 
<div class="wrapper"> 
 
    <div id="jrange" class="dates"> 
 
    <input /> 
 
    <div></div> 
 
    </div> 
 
</div>

+7

鏈路失效,不再可用。 –

+0

@GautamKrishnan,我更新了鏈接 – Mcestone

+0

該鏈接的圖像已全部損壞...此web開發人員需要更新其網站。 – Blairg23

17

你的劇本正是我一直在尋找。我分叉你原來的小提琴,並只對你的onSelect做一些微調,使它按你想要的方式工作。

onSelect: function(dateText, inst) { 
    var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val()); 
    var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val()); 
    var selectedDate = $.datepicker.parseDate($.datepicker._defaults.dateFormat, dateText); 


    if (!date1 || date2) { 
     $("#input1").val(dateText); 
     $("#input2").val(""); 
     $(this).datepicker(); 
    } else if(selectedDate < date1) { 
     $("#input2").val($("#input1").val()); 
     $("#input1").val(dateText); 
     $(this).datepicker(); 
    } else { 
     $("#input2").val(dateText); 
     $(this).datepicker(); 
    } 
} 

從原始部分丟失的內容只是一個檢查,用於將當前選定的日期值與已捕獲的日期值進行比較。

這裏是我的分叉小提琴: http://jsfiddle.net/sWbfk/

+1

一個更整齊的叉子:http://jsfiddle.net/o96fjdbk/ –

+0

好的,這是一個了不起的解決方案。我有一個問題,因爲我試圖完全理解如何/爲什麼這個工程。 它是有道理的,onSelect將是標記選舉日期的方法。對我來說沒有意義的是爲什麼beforeShowDay有實際上將高亮類添加到日期的行。我認爲beforeShowDay是在每天顯示日曆之前調用的。我使用這個來突出顯示在建立我的12個月日曆時的預訂日期(我已將這些日曆合併到了操作中)。那麼,當你選擇(onSelect)日期時,又是如何調用的? 謝謝,Thom – Thom

1

老兄,你的代碼確實是我需要的東西!

隨着傑米萊恩的糾正,我決定用它來製作一個插件。

這裏是鏈接的jsfiddle:http://jsfiddle.net/dxLRm/35/(鏈接更新2014年1月1日)

因爲我必須表現出一些代碼,這裏是我有:

(function ($) { 
$.prototype.rangedatepicker = function (o,x,y) { 
    var dp = $.datepicker, 
     cl = dp.markerClassName, 
     di = 'data-rdp-i', 
     df = 'data-rdp-f'; 

    switch(o) 
    { 
     case 'option': 
      return $(this).datepicker('option'); 
     case 'hide': 
      return $(this).datepicker('hide'); 
     case 'show': 
      return $(this).datepicker('show'); 
     case 'getInitialDate': 
      return dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(di)||''); 
     case 'getFinalDate': 
      return dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(df)||''); 
     case 'getRange': 
      var ini=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(di)||''), 
       fin=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(df)||''); 
      return (!ini&&!fin)?null:[ini,fin]; 
     case 'getNumDays': 
      var ini=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(di)||''), 
       fin=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(df)||''); 
      return (ini+0==0||fin+0==0)?0:Math.round((fin-ini)/86400000)+1; 
     case 'removeRange': 
      return $(this).attr(di,'').attr(df,'').datepicker('setDate',null); 
     case 'destroy': 
      return $(this).removeAttr(di).removeAttr(df).datepicker('destroy'); 
     case 'serialize': 
      return this[0].id+'_initial='+this[0].getAttribute(di)+'&'+this[0].id+'_final='+this[0].getAttribute(df); 
     default: 
     var defaults={ 
      allowSelectOneDay: false, 
      alwaysSetDateToFirstDay: true, 
      rangeEnabled: true, 
      rangeClass: 'ui-state-default ui-state-active'//'dp-highlight' 
     }; 
      o = $.extend({}, defaults, $.datepicker._defaults, o); 
     return $(this).each(function() { 
      if (!$.datepicker) return; 
      var t = this, 
       hd = !! ((' ' + t.className + ' ').indexOf(' ' + cl + ' ') + 1); 
      $(t).datepicker($.extend({}, o, { 
       beforeShowDay: function (d) { 
        if (o.rangeEnabled) { 
         var d1 = dp.parseDate(o.dateFormat, t.getAttribute(di) || ''), 
          d2 = dp.parseDate(o.dateFormat, t.getAttribute(df) || ''), 
          y = (function (d) { 
           try { 
            return o.beforeShowDay.call(t, d); 
           } catch (e) {} 
          })(d) || [true, '', null], 
          x = ((y && y[0] !== false) || !y) && d1 && ((d.getTime() == d1.getTime()) || (d2 && d >= d1 && d <= d2)); 
         return (!d1||!d2)?y||[true,'',null]:[y[0]&&x, (x ? o.rangeClass || defaults.rangeClass : '') + (y[1] ? ' ' + y[1] : ''), y[2]]; 
        } else { 
         return (function (d) { 
          try { 
           return o.beforeShowDay.call(t, d); 
          } catch (e) {} 
         })(d) || [true, '', null]; 
        } 
       }, 
       onSelect: function (dt, x) { 
        if (o.rangeEnabled) { 
         var i = t.getAttribute(di) || '', 
          f = t.getAttribute(df) || '', 
          d1 = dp.parseDate(o.dateFormat, i), 
          d2 = dp.parseDate(o.dateFormat, f), 
          s = dp.parseDate(o.dateFormat, dt); 
         if ((dt == i && dt == f) || (!o.allowSelectOneDay && ((dt == i && !f) || (dt == f && !i)))) { 
          t.removeAttribute(di); 
          t.removeAttribute(df); 
          $(t).datepicker('setDate', null); 
         } else if (!d1 || d2) { 
          t.setAttribute(di, dt); 
          t.removeAttribute(df); 
          o.alwaysSetDateToFirstDay && $(t).datepicker('setDate', s); 
         } else if (s < d1) { 
          t.setAttribute(df, i); 
          t.setAttribute(di, dt); 
          o.alwaysSetDateToFirstDay && $(t).datepicker('setDate', s); 
         } else { 
          t.setAttribute(df, dt); 
          o.alwaysSetDateToFirstDay && $(t).datepicker('setDate', d1); 
         } 
        } else { 
         t.removeAttribute(di); 
         t.removeAttribute(df); 
         $(t).datepicker('setDate', dp.parseDate(o.dateFormat, dt)); 
        } 

        try { 
         if($(t).datepicker('getDate'))o.onSelect.call(t, dt, x); 
        } catch (e) {} 
       } 
      })); 
     }); 
    } 
}; 
})(window.jQuery); 

你應該訪問小提琴並閱讀要做的事情列表!

任何想法或代碼片讚賞!

0

我在找一個日期範圍選擇器,我發現這個頁面。我嘗試了大多數建議,甚至在此展示,並將其轉化爲易於使用和集成的擴展:https://github.com/BuroRaDer/DateRangePicker。試試演示頁面,看看它是如何工作的。我想我可以把它變成一個真正的jQuery擴展,但現在我很滿意它的工作方式。

現場演示:

兩者都使用到它已經現在集成可用性日曆模塊的Drupal網站。

+0

爲什麼你創建不同的帳戶一次又一次地發佈相同的答案?您發佈了與此帖相同的答案@Charu – NSNoob

+0

來自@NSNoob的評論已過時(並且在第一位不正確),請刪除。 – fietserwin

0

我正在尋找即使沒有內聯也能正常工作的版本。我希望能夠點擊輸入字段來激發範圍日期選擇器。我能找到的所有範圍datepicker示例都是內聯的(包括上面的mcestone和Jamie Layne版本,這是分叉代碼的基礎)。

這裏的小提琴:http://jsfiddle.net/boson/pjffdtz2/

難的部分似乎是越來越日期選擇器來處理多個輸入不是內聯的時候。 Datepicker不會輕鬆處理兩個輸入,如果你想打開datepicker的焦點 - 肯定是一個'技巧'。如果您將日期選擇器與隱藏輸入(顯示:無)相關聯,請在可見輸入之前創建隱藏輸入,然後讓您的可見輸入在點擊事件中顯示日期選擇器,這一切都很好。

所以我把原來的答案,只是做了一些小的改動:

  • 在HTML中,創建日期選擇器關聯的隱藏輸入。在之前列出它的可見輸入。
  • 在html中,使用可見輸入的click事件來顯示與隱藏輸入關聯的日期選擇器。
  • 在Javascript日期選擇器onSelect中,暫時將日期選擇器置於內聯模式,直到兩個日期都被點擊。這允許您在datepicker關閉之前點擊多個日期(範圍'到'日期和'從'日期) - 這基本上將datepicker轉換爲多點擊日期選擇器。
  • 在datepicker onClose中,關閉內聯模式。這允許有人點擊輸入字段再次打開日期選擇器。
  • 在beforeShow,將日期選擇向下幾個像素,所以你可以看到輸入字段和日期選擇器

下面的代碼:

$(function() { 
 
    $(".rangepicker").datepicker({ 
 
    minDate: 0, 
 
    numberOfMonths: [2, 1], 
 
    beforeShow: function (input, inst) { 
 
     var rect = input.getBoundingClientRect(); 
 
     setTimeout(function() { 
 
\t  inst.dpDiv.css({ top: rect.top + 40, left: rect.left + 0 }); 
 
     }, 0); 
 
    }, 
 
    beforeShowDay: function(date) { 
 
     var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val()); 
 
     var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val()); 
 
     var isHighlight = 
 
     date1 && ((date.getTime() == date1.getTime()) || (date2 && date >= date1 && date <= date2)); 
 
     return [true, isHighlight ? "dp-highlight" : ""]; 
 
    }, 
 
    onSelect: function(dateText, inst) { 
 
     var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val()); 
 
     var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val()); 
 
     var selectedDate = $.datepicker.parseDate($.datepicker._defaults.dateFormat, dateText); 
 

 
     if (!date1 || date2) { 
 
     $("#input1").val(dateText); 
 
     $("#input2").val("");   
 
     } else if (selectedDate < date1) { 
 
      $("#input2").val($("#input1").val()); 
 
      $("#input1").val(dateText); 
 
     } else { 
 
      $("#input2").val(dateText); 
 
     } 
 
     $(this).data('datepicker').inline = true;   
 
     $(this).datepicker(); 
 
    }, 
 
    onClose: function() { 
 
     // Since we went inline as soon as the date input was clicked 
 
     // (to leave the datepicker up for both dates selection), 
 
     // turn inline back off again so date input click will once again 
 
     // display the datepicker 
 
     $(this).data('datepicker').inline = false; 
 
    } 
 
    }); 
 
});
.dp-highlight .ui-state-default { 
 
      background: #484; 
 
      color: #FFF; 
 
     }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script> 
 
<input type="text" id="input1_1" class="rangepicker" style="display: none"> 
 
<p> 
 
    Dates: 
 
    <label><b>To:</b></label> 
 
    <input type="text" id="input1" onclick="$('.rangepicker').datepicker('show');"> 
 
    <label><b>From:</b></label> 
 
    <input type="text" id="input2" onclick="$('.rangepicker').datepicker('show');"> 
 
    <button id="done">Done</button> 
 
</p>

許多事情離開改善。需要更好的輸入驗證。特別是想讓datepicker'Done'按鈕在內聯模式下工作,但datepicker不是爲這種情況設計的(當然,在datepicker中有一個可設置的Done按鈕標誌會很好)。所以現在,我有一個俗成的按鈕旁邊的輸入字段,實際上什麼都沒做(除了鼓勵用戶關閉日期選擇器關閉日期選擇器)。

1

我也一直在尋找一種方式來延長日期選擇器jQuery插件,利用引導造型和整個這個小寶石傳來:

Bootstrap-Date Range Picker由丹·格羅斯曼表示有工作代碼的一些活生生的實例。

以下是項目GitHub

最後,這裏是設計的簡單性和強大的截圖:

screenshot

0

謝謝,我需要這種代碼。這裏是我的代碼:

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> 
<link rel="stylesheet" href="/resources/demos/style.css"> 
<script  src="https://code.jquery.com/jquery-1.12.4.js"></script> 
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> 

<div id="Datepicker"></div> 
<p> 
<label><b>Checkin:</b></label> <label id="checkinDate"></label> 
<label><b>Checkout:</b></label> <label id="checkoutDate"></label> 
</p> 

/** Display Checkin Datepicker and Checkout DatePicker */ 
<script> 
datePicker(); 
function datePicker(){ 
    $(document).ready(function(){ 
     $("#Datepicker").datepicker({ 
     dateFormat: "MM d, yy", 
    minDate: 0, 
    maxDate: "+3M +0D", 
     beforeShowDay: dateRange, 
    onSelect: DRonSelect 
     }); 
    }); 
} 

function dateRange(date){ 
    var date1 = $.datepicker.parseDate("MM d, yy", $("#checkinDate").text()); 
    var date2 = $.datepicker.parseDate("MM d, yy", $("#checkoutDate").text()); 
    var isHighlight = date1 && ((date.getTime() == date1.getTime()) || (date2 && date >= date1 && date <= date2)); 
     $(document).ready(function(){ 
    // $("td.dp-highlight").text("Y"); 

}); 
    return [true, isHighlight ? "dp-highlight" : ""]; 
} 

function DRonSelect(dateText, inst) { 
    var date1 = $.datepicker.parseDate("MM d, yy", $("#checkinDate").text()); 
    var date2 = $.datepicker.parseDate("MM d, yy", $("#checkoutDate").text()); 
     if (!date1 || date2) { 
     $("#checkinDate").text(dateText); 
    $("#checkoutDate").text(""); 
     $("#Datepicker").datepicker(); 
     } 
     else { 
     if ($.datepicker.parseDate("MM d, yy", $("#checkinDate").text()) >= 
$.datepicker.parseDate("MM d, yy", dateText)) { 
      $("#checkinDate").text(dateText); 
      $("#checkoutDate").text(""); 
      $("#Datepicker").datepicker(); 
     } 
     else { 
     $("#checkoutDate").text(dateText); 
      $("#Datepicker").datepicker(); 
     } 
     } 
} 
</script> 

我的代碼是來自其他人的示例代碼,但日期選擇,日期範圍和higlights不同。我創建和保存代碼的jsfiddle

https://jsfiddle.net/kk585b4g/

+0

你可以給更多的理由,爲什麼你改變了一些零件。另一種方法是,複製其他答案很簡單。 – timiTao

+0

嗨Timitao。這裏的所有人都很友善,他們共享代碼並在此發佈代碼。我改變了一些部分,因爲我喜歡我修改的datepicker的結果。此外,我不能給出更多的理由,因爲我只需要像分享代碼/腳本一樣的幫助。我希望你的代碼也可以通過共享代碼來幫助我。 – Marvin

相關問題