Need some help?

I'm usually available for small jobs or problem solving with jQuery or css, at reasonable rates. Just get in touch.

Web Hosting

We recommend Clook for web hosting. UK based, great service and great value.

jQuery UI Datepicker, selecting weeks only

So here’s the situation. I wanted to be able to select a date from a drop-down calendar, but I wanted to restrict the selection of dates to Saturdays only, and I wanted to be able to click on any day in the week to select the Saturday. I envisaged this for booking a holiday cottage (or vacation rental, if you will) for a week at a time. Here’s how I adapted the jQuery UI Datepicker plugin.

In order to record which weeks are booked and which aren’t, I have a database table which holds the “week commencing” dates and an “available” field which holds true/false. I’m querying this once via PHP when the page loads, and storing the result in a JSON variable – this avoids the need for multiple queries on the database which slow down navigation between months.

I’m setting a number of options within datepicker – see the code for details.

When the input field is focussed, the datepicker is launched. I’m using the datepicker beforeShowDay event to call a function to check the availability for each day. If the day to be checked is a Saturday, the code searches the JSON data for a matching date. There are three possibilities here – either the date is found and it’s available, or the date is found and it’s booked, or the date isn’t found (if it’s too far in the future let’s say). In these three cases I’m returning a class of “available”, “booked” or “unavailable”, which I’m using to style the calendar. If the day isn’t a Saturday, then I’m returning the class of the previous Saturday, so that all the weekdays are assigned the same class as the Saturday. Only in the case of an available Saturday am I returning selectable true.

So far so good, now the calendar is constructed, and I’m using css to colour the dates according to the class assigned to them. Now, I’m using some jQuery to assign a class to a hovered row, and then to allow a click event on any element in the row to generate a click event on the Saturday on the row to select the date. This took some experimentation to prevent the click being propagated up and down the DOM, which caused a delay after the date was selected.

Right, enough talk. Here’s my php code to build the json data:

$result = mysql_query("SELECT week_commencing,available FROM test_datepicker");
$i=0;
while($row = mysql_fetch_array($result))
    {
    availability[$i]=array("date"=>$row['week_commencing'],"status"=>$row['available'])?"available":"booked");
    $i++;
    }
$availabilityjson =  json_encode($availability);

And here’s the jQuery code for datepicker and the hover and “click row” behaviour:

var $availability = <?php echo $availabilityjson;?>;//echo the json data from php
var $prev_sat_class = "unavailable";//set global variable for recording status of preceding Saturday
$(function() {
$( "#pickdate" ).datepicker({//instantiate the datepicker
        dateFormat: 'dd MM yy',
	beforeShowDay: checkAvailability,//call a function to check each date
	firstDay: 6,//set Saturday as the first day
	minDate: new Date(),//don't allow anything before today to be selected
	maxDate: "31 December 2011",//set a "latest selectable date"
	prevText: "<",//just set the previous and next links to be < and >
	nextText: ">",
	showOtherMonths: true,//show end dates from the previous month and first dates from the next month in the calendar - this makes the selection of weeks easier
	selectOtherMonths: true,//and allow these dates to be selected
	changeMonth: true,//display the month as a dropdown
	changeYear: true,//and the year
	yearRange: "0:+1",//display this year and next year
	onSelect:function(input,inst){$prev_sat_class = "unavailable";},//reset the "previous Saturday" class if a date is selected - to prevent error if the datepicker is opened again
	onChangeMonthYear:function(input,inst){$prev_sat_class = "unavailable";} //and similarly reset it if the month or year is changed
});

$("tbody tr").live("hover",function() {//set a hover function for rows using live
	if($(this).children().first().hasClass("available"))//if the row has the Saturday set as available...
		{
		$(this).toggleClass("active");//...add class to enable the hover behaviour...
		$(this).click(function(event){//... and add an event to pass a click on the row to the available Saturday
			$(".active").children().first().click();
			});
		$(this).children().first().click(function(event){
			event.stopPropagation();//add another event to the Saturday to stop the click bubbling up the DOM
			})
                }
});//end hover event
			
})

And here are the functions called from datepicker:

function checkAvailability(showdate){//function called by beforeShowDay
$available = false; $return_class = "unavailable";//set defaults as not selectable/unavailable
if (showdate.getDay() == 6 && showdate > new Date()) //check only future Saturdays for availability
	{
	$checkdate = $.datepicker.formatDate('yy-mm-dd', showdate);
	$datestatus = checkDate($checkdate);//call function to see if the date is available from the json data
	$return_class = $datestatus;//set the class to the status for display purposes
	if ($datestatus == "available") $available = true;//if the date is available, set it to be selectable...
	else $available = false;//...otherwise set the date as not selectable
	$prev_sat_class = $return_class;//return class for subsequent days will be the same as that for the previous Saturday
	}
else $return_class = $prev_sat_class;//if not a future Saturday, set class same as previous Saturday
return [$available, $return_class];//return true/false for selectable, plus the appropriate class for display
}

function checkDate(newdate){//function to read the json data to check whether the week is available
$returnstatus =  "unavailable";//default value if the date is not found
for(var i = 0; i < $availability.length; i++)
	{
	  if($availability[i].date == newdate)
	  {
		$returnstatus= $availability[i].status;//if date is found, read the status
	  }
	}
return $returnstatus;
}

There's a demo here, which I've tested in IE6, IE7, IE8, Firefox3, Chrome, Opera 9, Opera 10 and Safari 4, all on Win/XP, and Safari 5 on Mac OS X /Snow Leopard. View the source to see the css and html. Feel free to leave comments, questions and suggestions for improvement below.

3 responses to “jQuery UI Datepicker, selecting weeks only”

  1. Carlos says:

    Hi, nice solution, another alternative to get it, is to use kalendar, take a look: jQuery datepicker – kalendar.

    Regards.

  2. Simon says:

    Narendra

    No, datepicker doesn’t provide this.

  3. Narendra says:

    Hi,
    is it posible that we can show month and year in one dropdown on jquery date picker like November 2010.

Useful? Interesting? Leave me a comment

I've yet to find a way of allowing code snippets to be pasted into Wordpress comments - so if you're trying to do this you'd be better off using the contact form.