Tuesday, August 13, 2013

Add a JQuery DatePicker and limit it to show only the dates you specify

I needed to help users avoid mistakes by limiting the dates available to them in the calendar that appears when the JQuery datepicker is used.  Here's what I did.
I had a form field that looks like this:
The html (framework-generated and a little ugly) looks like this:

 The id of the end date input is "end_date". The little calendar icon was added by simply using JQueryUI to attach the DatePicker to the end_date input like this:

Most of the options specified in the JQueryUI datepicker call above are optional.  They give me a datepicker like this that only lets people pick a date between today (minDate: 0) and 180 days from now (maxDate: 180):


But I have two kinds of auction.  Daily auctions end every day of the year.  Weekly auctions (my normal type) end every two weeks.  So if the daily auction is not checked, I want only every other Wednesday to show on the pickable calendar. 

Luckily, JQueryUI DatePicker has a property that lets me do just that.  All I have to do is add a beforeShowDay option to the datepicker to tell JQuery "Before you show each day, run this function, and apply its results to how you show that day."  JQueryUI supplies the day as a Date object argument to the function, and I have to return an array of two or three elements telling what to do with that day.  The first element is true or false and tells whether the day is enabled.  The second element gives a CSS class for showing the day the way you want, or '' if you just want to accept the default.  The third element is an optional popup tool-tip for the day.

JQuery runs my logic on every day before that day on the calendar is shown.  So I wrote some logic that only returns true every other Wednesday.


Then I put that logic into the DatePicker call as a new property that always returns true (always show) for daily auctions or returns true every other Wednesday for regular auctions:

So if daily is unchecked, the DatePicker looks like this:
Here's the code so you can copy and paste:
$(document).ready(function() {
     $('#end_date').datepicker({
        showOn: "both",
        changeMonth: true,
        changeYear: true,
        minDate: 0,
        maxdate: 180,
        numberOfMonths: 2,
        beforeShowDay: function(day) {
            if ($('#daily_auction').is(':checked')) return [true,''];
            var n = (Math.floor(day.getTime() / 24 / 3600 / 1000) + 1)/14, // Show only auction ends
            showDay = (n - Math.floor(n)) === 0;
            return [showDay, ''];
        },
        buttonImage: "/images/calendar.gif",
        buttonImageOnly: true,
        dateFormat: 'yy-mm-dd'
    });
});

No comments: