jQuery datepicker- 2 inputs/textboxes and restricting range

JqueryJquery PluginsDatepickerJquery Ui-Datepicker

Jquery Problem Overview


I am using the jQuery Datepicker widget with two input boxes, one for the "From" date and the second with the "To" date. I am using the jQuery Datepicker functional demo as a basis for getting the two input boxes to work with each other, but I need to be able to add these additional restrictions:

  1. Date range can be no earlier than 01 December 2008

  2. "To" date can be no later than today

  3. Once a "From" date is selected, the "To" date can only be within a range of 7 days after the "From" date

  4. If a "To" date is selected first, then the "From" date can only be within the range of 7 days before the "To" date (with the limit of 01 December being the first selectable date)

I can't seem to get all of the above working together.

In summary, I would like to be able to select a range of up to 7 days between 01 December and today (I realise I am posting this on 1st December so will only get today for the moment).

My code so far

$(function () {

$('#txtStartDate, #txtEndDate').datepicker(
            {
            showOn: "both",
            beforeShow: customRange,
            dateFormat: "dd M yy",
            firstDay: 1, 
            changeFirstDay: false
            });
});
            
function customRange(input) 
{ 

return {
         minDate: (input.id == "txtStartDate" ? new Date(2008, 12 - 1, 1) : null),
         minDate: (input.id == "txtEndDate" ? $("#txtStartDate").datepicker("getDate") : null), 
         maxDate: (input.id == "txtStartDate" ? $("#txtEndDate").datepicker("getDate") : null)
       }; 
}

I'm missing the 7 day range restriction and also preventing a "To" date selection before 01 December 2008 or after today. Any help would be much appreciated, Thanks.

Jquery Solutions


Solution 1 - Jquery

Many thanks for your help Ben, I have built upon your posts and have come up with this. It is now complete and works brilliantly!

Here's a Working Demo. Add /edit to the URL to see the code

Complete Code below-

$(function () 
{   
    $('#txtStartDate, #txtEndDate').datepicker({
        showOn: "both",
        beforeShow: customRange,
        dateFormat: "dd M yy",
        firstDay: 1, 
        changeFirstDay: false
    });

});

function customRange(input) { 
    var min = new Date(2008, 11 - 1, 1), //Set this to your absolute minimum date
        dateMin = min,
        dateMax = null,
        dayRange = 6; // Set this to the range of days you want to restrict to

    if (input.id === "txtStartDate") {
        if ($("#txtEndDate").datepicker("getDate") != null) {
            dateMax = $("#txtEndDate").datepicker("getDate");
            dateMin = $("#txtEndDate").datepicker("getDate");
            dateMin.setDate(dateMin.getDate() - dayRange);
            if (dateMin < min) {
                dateMin = min;
            }
        }
        else {
            dateMax = new Date; //Set this to your absolute maximum date
        }                      
    }
    else if (input.id === "txtEndDate") {
        dateMax = new Date; //Set this to your absolute maximum date
        if ($("#txtStartDate").datepicker("getDate") != null) {
            dateMin = $("#txtStartDate").datepicker("getDate");
            var rangeMax = new Date(dateMin.getFullYear(), dateMin.getMonth(),dateMin.getDate() + dayRange);
                                                  
            if(rangeMax < dateMax) {
                dateMax = rangeMax; 
            }
        }
    }
    return {
        minDate: dateMin, 
        maxDate: dateMax
    };     
}

Solution 2 - Jquery

I realise I'm a little late to the party, but here is how I modified the working example code. I didn't need to set a specific maximum and minimum date, just didn't want a date range overlap, so I just let them set each other:

jQuery(function() {
  jQuery('#calendardatetime_required_to, #calendardatetime_required_from').datepicker('option', {
    beforeShow: customRange
  });
});

function customRange(input) {
  if (input.id == 'calendardatetime_required_to') {
    return {
      minDate: jQuery('#calendardatetime_required_from').datepicker("getDate")
    };
  } else if (input.id == 'calendardatetime_required_from') {
    return {
      maxDate: jQuery('#calendardatetime_required_to').datepicker("getDate")
    };
  }
}

(My datepickers were already initialised in a script further up, but it's just default settings.)

Seems to do what I need it to :)

See here for my example.

Solution 3 - Jquery

Alright, how about this:

function customRange(input) 
{ 
    var min = new Date(2008, 12 - 1, 1);
	var dateMin = min;
	var dateMax = null;
	
	if (input.id == "txtStartDate" && $("#txtEndDate").datepicker("getDate") != null)
	{
		dateMax = $("#txtEndDate").datepicker("getDate");
		dateMin = $("#txtEndDate").datepicker("getDate");
		dateMin.setDate(dateMin.getDate() - 7);
		if (dateMin < min)
		{
			dateMin = min;
		}			
	}
	else if (input.id == "txtEndDate")
	{
		dateMax = new Date();
		if ($("#txtStartDate").datepicker("getDate") != null)
		{
			dateMin = $("#txtStartDate").datepicker("getDate");
			dateMax = $("#txtStartDate").datepicker("getDate");
			dateMax.setDate(dateMax.getDate() + 7); 
		}
	}
    return {
     minDate: dateMin, 
     maxDate: dateMax
   }; 
	
}

This is the best I could come up with that met all of your requirements (I think...)

Solution 4 - Jquery

Consider using rangeSelect to have one control instead of two.

To achieve what you are after, I suppose you need to add an onSelect listener and then call datepicker( "option", settings ) to change the settings.

Solution 5 - Jquery

Your start date for txtStartDate isn't working because your second minDate is being set to null when it checks the input.id the second time. Also, maxDate should be checking for txtEndDate, not txtStartDate. Try this:

	function customRange(input) 
{ 
	var mDate = (input.id == "txtStartDate" ? new Date(2008, 12 - 1, 1) : $("#txtStartDate").datepicker("getDate"));
	return {
         minDate: mDate, 
         maxDate: (input.id == "txtEndDate" ? $("#txtStartDate").datepicker("getDate").getDate() + 5 : null)
       }; 
}

I don't know why the '+ 5' instead of '+ 7', but if I add 0, I get a selectable date range of the day I picked plus the next.

Solution 6 - Jquery

Here is a solution I came up with after a lot of digging for a solution to what I think is a common problem. This effectively 'bounces' the inputs around a shared input range of compatible days. Meaning - if I have two fields, either one can be used to constrain the other, and the other could redefine the original if necessary. The goal of this is to always ensure that there is only a finite range of days (or months or whatever) between the the two fields. This specific example also limits the amount of time into the future that something could be selected in either field (e.g. 3 months).


$("#startdate").datepicker({
minDate: '+5',
maxDate: '+3M',
changeMonth: true,
showAnim: 'blind',
onSelect: function(dateText, inst){



// Capture the Date from User Selection
var oldDate = new Date(dateText);
var newDate = new Date(dateText);

// Compute the Future Limiting Date
newDate.setDate(newDate.getDate()+5);
   
   
// Set the Widget Properties
$("#enddate").datepicker('option', 'minDate', oldDate);
$("#enddate").datepicker('option', 'maxDate', newDate);
   
}




});




$("#enddate").datepicker({
minDate: '+5',
maxDate: '+3M',
changeMonth: true,
showAnim: 'blind',
onSelect: function(dateText, inst){



// Capture the Date from User Selection
var endDate = new Date(dateText);
var startDate = new Date(dateText);

// Compute the Future Limiting Date
startDate.setDate(startDate.getDate()-5);
   
// Set the Widget Properties
$("#startdate").datepicker('option', 'minDate', startDate);
$("#startdate").datepicker('option', 'maxDate', endDate);
   
}




});

});

Solution 7 - Jquery

this is how i use it:

function customRange(input)
{
	var min = new Date();
	return {
		minDate: ((input.id == "txtStartDate") ? min : (input.id == "txtEndDate" ? $("#txtStartDate").datepicker("getDate") : null)),
		maxDate: (input.id == "txtStartDate" ? $("#txtEndDate").datepicker("getDate") : null)
	};
}

Solution 8 - Jquery

This is how I have done it. I have taken the source from the Jquery UI website and modified it to add your constraints.

$(document).ready(function ()
{      
  var dates = $('#StartDate, #EndDate').datepicker({
        minDate: new Date(2008, 11, 1), 
        maxDate: "+0D",
        dateFormat: "dd M yy",
        changeMonth: true,
        changeYear: true,
        onSelect: function (selectedDate)
        {
            var option = this.id == "StartDate" ? "minDate" : "maxDate",
				instance = $(this).data("datepicker"),
				date = $.datepicker.parseDate(
					instance.settings.dateFormat ||
					$.datepicker._defaults.dateFormat,
					selectedDate, instance.settings);
            var edate;
            var otherOption;
            var d;
            if (option == "minDate")
            {
                otherOption = "maxDate";
                d = date.getDate() + 7;
            }
            else if (option == "maxDate")
            {
                otherOption = "minDate";
                d = date.getDate() - 7;
            }

            var m = date.getMonth();
            var y = date.getFullYear();
            edate = new Date(y, m, d);

            dates.not(this).datepicker("option", option, date);
            dates.not(this).datepicker("option", otherOption, edate);
        }
    });
});

Initial Idea from: <http://jqueryui.com/demos/datepicker/#date-range>

Note: You would also need an option to reset/clear the dates (i.e. if a user chooses a 'From date', the 'To date' becomes limited. After choosing a 'From date' if the user now chooses a 'To date', the From date also gets limited. You need to have a clear option to allow the user to choose a different "From" date now.)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRuss CamView Question on Stackoverflow
Solution 1 - JqueryRuss CamView Answer on Stackoverflow
Solution 2 - JqueryRobin DuckettView Answer on Stackoverflow
Solution 3 - JqueryBen KoehlerView Answer on Stackoverflow
Solution 4 - JquerykgiannakakisView Answer on Stackoverflow
Solution 5 - JqueryBen KoehlerView Answer on Stackoverflow
Solution 6 - JqueryDavid BigelowView Answer on Stackoverflow
Solution 7 - JquerygabyView Answer on Stackoverflow
Solution 8 - JqueryescistView Answer on Stackoverflow