views:

17921

answers:

14

I am using the Jquery datepicker plugin 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.

+2  A: 

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.

kgiannakakis
Using one control is a possiblity, although I'd prefer to try and keep the "From and "To" dates in separate controls to maintain the current UI consistency.
Russ Cam
+2  A: 

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.

Ben Koehler
This solves the selectable range of 7 days from "From" date to "To" date but it errors if selecting a "To" date before a "From" date has been selected.
Russ Cam
Yeah, I missed some of your requirements on the first pass. See my other answer.
Ben Koehler
+8  A: 

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

Ben Koehler
+5  A: 

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
    };     
}
Russ Cam
A: 

Russ Cam - How do you get the input boxes to work with each other if you are using an inline calendar instead? I know that's not what you did here but that's what I'm trying to achieve and can't get the date range to be reflected in two form fields for startDate and endDate.

I think the reason it will work for the popup calendar and not for an inline calendar is that the customRange is calculated before showing the calendar. You would need to change the minDate and/or maxDate values based on a selection on the other calendar for inline calendars.
Russ Cam
I imagine that this could be achieved with event handlers
Russ Cam
A: 

What kind of event handlers would you suggest, can you give me some sample codes so I can see what you mean?

Can I suggest that you open a new question and reference this one?
Russ Cam
Take a look at the onSelect callback function that is raised when a date is selected - http://docs.jquery.com/UI/Datepicker/datepicker#options
Russ Cam
A: 

halloo.. thanks for the tutorial i was tried your tutorial, but i have problem with your code. costumRange is undefined :(

See the working demo that I have posted on my answer. The code works fine
Russ Cam
A: 

two input boxes, how to let the second input field be changed to 1 day after dynamically, when the first one selected

Jason
Jason, please use your question for additional info. Posting a question on a question will not yield any answers. Have a look at your question here - http://stackoverflow.com/questions/1525078/jquery-datepicker-2-inputs-textboxes/1525097#1525097 I have posted a working answer for you. If it is useful, please vote it up and if it answers your question, then please mark it as accepted.
Russ Cam
A: 

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)
    };
}
gaby
A: 

gaby, how would you modify your solution (that works well btw), to set minDate for EndDate as today's date (end of "event" can't end in the past, that's simple logic).

+2  A: 

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.

Robin Duckett
A: 

how do u select the time range as well if you have a time specified in your date picker? Like.

From Date and Time should not be greater then To Date and Time?

Mehul
@Mehul - Welcome to stackoverflow! You should post your question as a question on the site rather than as an answer to another question. That way, you're likely to get more people looking at it and thus get a satisfactory answer.
Russ Cam
A: 

Hi dear, I have tried to implement the same control you are looking for using jquery. Please follow the link http://aspnet-ajax-aspnetmvc.blogspot.com/2010/09/jquery-date-range-plugin.html

Thanks,

Mohan Prajapati

Mohan Prajapati
A: 

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);

    }

  });

David Bigelow