{"id":1061,"date":"2010-09-28T08:35:39","date_gmt":"2010-09-28T07:35:39","guid":{"rendered":"http:\/\/www.simonbattersby.com\/blog\/?page_id=1061"},"modified":"2010-11-22T09:10:58","modified_gmt":"2010-11-22T08:10:58","slug":"jquery-ui-datepicker-select-weeks-only","status":"publish","type":"page","link":"https:\/\/www.simonbattersby.com\/blog\/jquery-ui-datepicker-select-weeks-only\/","title":{"rendered":"jQuery UI Datepicker, selecting weeks only"},"content":{"rendered":"<p>So here&#8217;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&#8217;s how I adapted the <a href=\"http:\/\/jqueryui.com\/demos\/datepicker\/\" title=\"jQuery UI datepicker\">jQuery UI Datepicker<\/a> plugin.<\/p>\r\n\r\n<p>In order to record which weeks are booked and which aren&#8217;t, I have a database table which holds the &#8220;week commencing&#8221; dates and an &#8220;available&#8221; field which holds true\/false. I&#8217;m querying this once via PHP when the page loads, and storing the result in a JSON variable &#8211; this avoids the need for multiple queries on the database which slow down navigation between months. <\/p>\r\n\r\n<p>I&#8217;m setting a number of options within datepicker &#8211; see the code for details.<\/p>\r\n\r\n<p>When the input field is focussed, the datepicker is launched. I&#8217;m using the datepicker <code>beforeShowDay<\/code> 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 &#8211; either the date is found and it&#8217;s available, or the date is found and it&#8217;s booked, or the date isn&#8217;t found (if it&#8217;s too far in the future let&#8217;s say). In these three cases I&#8217;m returning a class of &#8220;available&#8221;, &#8220;booked&#8221; or &#8220;unavailable&#8221;, which I&#8217;m using to style the calendar. If the day isn&#8217;t a Saturday, then I&#8217;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 <code>true<\/code>.<\/p>\r\n\r\n<p>So far so good, now the calendar is constructed, and I&#8217;m using css to colour the dates according to the class assigned to them. Now, I&#8217;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.<\/p>\r\n\r\n<p>Right, enough talk. Here&#8217;s my php code to build the json data:<\/p>\r\n\r\n<pre>$result = mysql_query(\"SELECT week_commencing,available FROM test_datepicker\");\r\n$i=0;\r\nwhile($row = mysql_fetch_array($result))\r\n    {\r\n    availability[$i]=array(\"date\"=&gt;$row['week_commencing'],\"status\"=&gt;$row['available'])?\"available\":\"booked\");\r\n    $i++;\r\n    }\r\n$availabilityjson =  json_encode($availability);\r\n<\/pre>\r\n\r\n<p>And here&#8217;s the jQuery code for datepicker and the hover and &#8220;click row&#8221; behaviour:<\/p>\r\n\r\n<pre>\r\nvar $availability = &lt;?php echo $availabilityjson;?&gt;;<span class=\"code_comment\">\/\/echo the json data from php\r\n<\/span>var $prev_sat_class = \"unavailable\";<span class=\"code_comment\">\/\/set global variable for recording status of preceding Saturday\r\n<\/span>$(function() {\r\n$( \"#pickdate\" ).datepicker({<span class=\"code_comment\">\/\/instantiate the datepicker\r\n<\/span>        dateFormat: 'dd MM yy',\r\n\tbeforeShowDay: checkAvailability,<span class=\"code_comment\">\/\/call a function to check each date\r\n<\/span>\tfirstDay: 6,<span class=\"code_comment\">\/\/set Saturday as the first day\r\n<\/span>\tminDate: new Date(),<span class=\"code_comment\">\/\/don't allow anything before today to be selected\r\n<\/span>\tmaxDate: \"31 December 2011\",<span class=\"code_comment\">\/\/set a \"latest selectable date\"\r\n<\/span>\tprevText: \"&lt;\",<span class=\"code_comment\"><span class=\"code_comment\">\/\/just set the previous and next links to be &lt; and <\/span>&gt;\r\n<\/span>\tnextText: \"&gt;\",\r\n\tshowOtherMonths: true,<span class=\"code_comment\">\/\/show end dates from the previous month and first dates from the next month in the calendar - this makes the selection of weeks easier\r\n<\/span>\tselectOtherMonths: true,<span class=\"code_comment\">\/\/and allow these dates to be selected\r\n<\/span>\tchangeMonth: true,<span class=\"code_comment\">\/\/display the month as a dropdown\r\n<\/span>\tchangeYear: true,<span class=\"code_comment\">\/\/and the year\r\n<\/span>\tyearRange: \"0:+1\",<span class=\"code_comment\">\/\/display this year and next year\r\n<\/span>\tonSelect:function(input,inst){$prev_sat_class = \"unavailable\";},<span class=\"code_comment\">\/\/reset the \"previous Saturday\" class if a date is selected - to prevent error if the datepicker is opened again\r\n<\/span>\tonChangeMonthYear:function(input,inst){$prev_sat_class = \"unavailable\";} <span class=\"code_comment\">\/\/and similarly reset it if the month or year is changed\r\n<\/span>});\r\n\r\n$(\"tbody tr\").live(\"hover\",function() {<span class=\"code_comment\">\/\/set a hover function for rows using live\r\n<\/span>\tif($(this).children().first().hasClass(\"available\"))<span class=\"code_comment\">\/\/if the row has the Saturday set as available...\r\n<\/span>\t\t{\r\n\t\t$(this).toggleClass(\"active\");<span class=\"code_comment\">\/\/...add class to enable the hover behaviour...\r\n<\/span>\t\t$(this).click(function(event){<span class=\"code_comment\">\/\/... and add an event to pass a click on the row to the available Saturday\r\n<\/span>\t\t\t$(\".active\").children().first().click();\r\n\t\t\t});\r\n\t\t$(this).children().first().click(function(event){\r\n\t\t\tevent.stopPropagation();<span class=\"code_comment\">\/\/add another event to the Saturday to stop the click bubbling up the DOM\r\n<\/span>\t\t\t})\r\n                }\r\n});<span class=\"code_comment\">\/\/end hover event\r\n<\/span>\t\t\t\r\n})<\/pre>\r\n\r\n<p>And here are the functions called from datepicker:<\/p>\r\n\r\n<pre>function checkAvailability(showdate){<span class=\"code_comment\">\/\/function called by beforeShowDay\r\n<\/span>$available = false; $return_class = \"unavailable\";<span class=\"code_comment\">\/\/set defaults as not selectable\/unavailable\r\n<\/span>if (showdate.getDay() == 6 && showdate &gt; new Date()) <span class=\"code_comment\">\/\/check only future Saturdays for availability\r\n<\/span>\t{\r\n\t$checkdate = $.datepicker.formatDate('yy-mm-dd', showdate);\r\n\t$datestatus = checkDate($checkdate);<span class=\"code_comment\">\/\/call function to see if the date is available from the json data\r\n<\/span>\t$return_class = $datestatus;<span class=\"code_comment\">\/\/set the class to the status for display purposes\r\n<\/span>\tif ($datestatus == \"available\") $available = true;<span class=\"code_comment\">\/\/if the date is available, set it to be selectable...\r\n<\/span>\telse $available = false;<span class=\"code_comment\">\/\/...otherwise set the date as not selectable\r\n<\/span>\t$prev_sat_class = $return_class;<span class=\"code_comment\">\/\/return class for subsequent days will be the same as that for the previous Saturday\r\n<\/span>\t}\r\nelse $return_class = $prev_sat_class;<span class=\"code_comment\">\/\/if not a future Saturday, set class same as previous Saturday\r\n<\/span>return [$available, $return_class];<span class=\"code_comment\">\/\/return true\/false for selectable, plus the appropriate class for display\r\n<\/span>}\r\n\r\nfunction checkDate(newdate){<span class=\"code_comment\">\/\/function to read the json data to check whether the week is available\r\n<\/span>$returnstatus =  \"unavailable\";<span class=\"code_comment\">\/\/default value if the date is not found\r\n<\/span>for(var i = 0; i &lt; $availability.length; i++)\r\n\t{\r\n\t  if($availability[i].date == newdate)\r\n\t  {\r\n\t\t$returnstatus= $availability[i].status;<span class=\"code_comment\">\/\/if date is found, read the status\r\n<\/span>\t  }\r\n\t}\r\nreturn $returnstatus;\r\n}<\/pre>\r\n\r\n<p>There's a demo <a href=\"\/demos\/datepicker_demo.php\" title=\"jQuery UI datepicker demo\">here<\/a>, 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.<\/p>\r\n","protected":false},"excerpt":{"rendered":"<p>So here&#8217;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 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1061","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.simonbattersby.com\/blog\/wp-json\/wp\/v2\/pages\/1061","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.simonbattersby.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.simonbattersby.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.simonbattersby.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.simonbattersby.com\/blog\/wp-json\/wp\/v2\/comments?post=1061"}],"version-history":[{"count":0,"href":"https:\/\/www.simonbattersby.com\/blog\/wp-json\/wp\/v2\/pages\/1061\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.simonbattersby.com\/blog\/wp-json\/wp\/v2\/media?parent=1061"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}