views:

1131

answers:

8

Is there a Javascript or some library that would create a datepicker for a webpage (similar to Jquery UI DatePicker that would only allow certain dates to be clickable and highlighted.

For example on server side, I could specify a array of days to enable to be selected.

A: 

What's wrong with the jQuery UI Datepicker?

Matt Ball
He doesn't want a range, he wants to cherry pick the 'OK' days.
benjynito
Thanks - that wasn't obvious at all.
Matt Ball
+3  A: 

You could start by using the jquery ui datepicker. Download the latest development bundle and work from ui.datepicker.js. See _generateHTML. Look for the variable unselectable. If your server side code could generate some script - it could populate some new setting you could extend the date picker to accept. Then add a check to that list of valid dates in this line where unselectable is set. Note that it appears the date picker allows dates input by keyboard outside of the valid range.

If you're already using jquery ui I would probably just override the _generateHTML prototype after you've loaded the jquery UI script.

benjynito
Not a great idea to recommend hacking the internals, especially to provide existing functionality.
Rob Van Dam
A: 

Perhaps you could extend the DatePicker to allow for disabled/enabled dates... I believe you could remove the click handler for disabled dates, making them unclickable. Then just tweak the CSS for disabled dates and they can be "greyed out".

Dave Swersky
A: 

I made an app just like that (a web-based date-picker with various dates prohibited) using YUI Calendar and a bunch of custom code. That being said, I did this before I'd discovered the wondrous joys of jQuery (and the "god, this isn't half as good of jQuery, but at least it uses jQuery methods" of jQuery UI). If I were to do it again, I'd definitely use jQuery UI (despite it's many failings) as my basis; mixing libraries is more hassle than dealing with jQuery UI's immaturity.

machineghost
+1  A: 

Try dijit.Calendar There is an isDisabledDate property you can set in markup or in JavaScript to a function. See the second example. The method to disable dates is called for each day as it is rendered. The function could do something like determine if a pattern is followed (is it a weekend?) or look it up against some static table (Array) you provide from the server, like busy days or holidays. The getClassForDate method can be overridden to return a CSS class.

peller
+14  A: 

The Datepicker beforeShowDay() event is intended for exactly this purpose. Here's an example where the set of allowed dates is relatively small for purposes of illustration. Depending on how many dates you have and how they are chosen, you could instead write a method that programmatically selected dates (say by ignoring weekends, the 1st and 15th of every month, etc). Or you could combine both techniques, say remove weekends and a fixed list of holidays.

$(function() {
    // this could be a static hash, generated by the server, or loaded via ajax
    // if via ajax, make sure to put the remaining code in a callback instead.
    var dates_allowed = {
          '2009-12-01': 1,
          '2009-12-25': 1,
          '2010-09-28': 1,
    };

    $('#datepicker').datepicker({
        // these aren't necessary, but if you happen to know them, why not
        minDate: new Date(2009, 12-1, 1),
        maxDate: new Date(2010, 9-1, 28),

        // called for every date before it is displayed
        beforeShowDay: function(date) {
            var date_str = [
                date.getFullYear(),
                date.getMonths() + 1,
                date.getDay()
            ].join('-');

            if (dates_allowed[date_str]) {
                return [true, 'good_date', 'This date is selectable'];
            } else {
                return [false, 'bad_date', 'This date is NOT selectable'];
            }
        }
    });
});

The return values are

[0]: boolean selectable or not,
[1]: CSS class names to apply if any (make sure to return '' if none),
[2]: Tooltip text (optional)

Note that the date variable given in the callback is an instance of a Date object representing the given day, not a text version of that date in the specified format. So for instance, you could generate the list of allowable dates in one format while displaying dates in the datepicker in a different format (e.g. so you wouldn't have to transform dates from a DB when generating the page).

See also http://stackoverflow.com/questions/501943/can-the-jquery-ui-datepicker-be-made-to-disable-saturdays-and-sundays-and-holida

Rob Van Dam
Interesting answer... I have to investigate more into this...
Carles
Nice, didn't realize there was existing functionality. +1
benjynito
A: 

I've been using The Coolest Javascript Calendar for years and it has the ability to disable some days of the calendar. Just check it out, I'm using it within al sorts of ASP.NET projects.

More info on disabling dates can be found here.

Jochen
+1  A: 

Elaborating Rob Van Dam's answer, here is a code sample (using jQuery UI datepicker) for fetching enabled dates using AJAX. I use AJAX to query a PHP page that returns the enabled date from a database (because I only want to show dates where I have actual data).

The idea is to do the AJAX query each time the user change month and then store the enabled dates for this month in a global array (allowedDates) that is later used by beforeShowDay.

Of course, you could do the AJAX query in beforeShowDay, but this would be quite inneficient due to the high number of AJAX queries (more than 30 for each month).

var allowedDates = new Object();

function queryAllowedDates (year, month, id) {
  $.ajax({
    type: 'GET',
    url: 'calendar_days.php',
    dataType: 'json',
    success: function(response) { 
      allowedDates[id] = response.allowedDates;
    },
    data: {year:year,month:month},
    async: false
  });
}

$("#datepicker1").datepicker({
  dateFormat: 'dd.mm.yy', 
  changeMonth: true, 
  changeYear: true ,
  beforeShow: function (input) {
    var currentDate = $(input).datepicker('getDate');
    var id = $(input).attr('id');
    queryAllowedDates(currentDate.getFullYear(), currentDate.getMonth()+1,id);
  },
  onChangeMonthYear: function (year, month, inst) {
    queryAllowedDates(year, month, inst.input.attr('id'));
  },
  beforeShowDay: function (day) {
    var id = $(this).attr('id');

    var date_str = [
      day.getFullYear(),
      day.getMonth() + 1,
      day.getDate()
    ].join('-');

    if (allowedDates[id] != undefined && allowedDates[id][date_str]) {
      return [true, 'good_date', 'This date is selectable'];
    } else {
      return [false, 'bad_date', 'This date is NOT selectable'];
    } 
  }
});

In this example, the PHP page returns a JSON array containing something like :

{"allowedDates":{"2008-12-04":1,"2008-12-11":1}}
Julien