mcestone mcestone - 6 months ago 133
jQuery Question

Date range picker on jquery ui datepicker

I created a date range picker using jquery ui where you can use the same inline calendar to make both of your date selections.

See my fiddle here: 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();
}
}
});


What I want to be able to do is a range selector like this: http://jsfiddle.net/D3wLX/1/

If you select an earlier date then the earlier date is automatically made the first date in the range and the middle dates are highlighted. Right now on my original jquery ui solution it will just put the earlier date in the second input and not highlight the dates in between.

Answer

I found the answer here:

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

Great tutorial

$.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>