Dan Bowling
Dan Bowling

Reputation: 1225

Dojo's dijit.calendar and isDisabledDate

I'd like to use the dijit.calendar widget, but be able to set disabled dates from an array of dates. All the examples point out how to disable weekends, but I need to disable special dates too.

Can anyone point me in the right direction to utilize a custom function in the isDisabledDate, rather than just whats in dojo.date.locale?

I've tried writing a function, and putting it inside the isDisabledDate attribute, but all I get is errors.

Upvotes: 2

Views: 2724

Answers (3)

Mohan
Mohan

Reputation: 11

You can add list of holidays in an array with its timestamp and use indexOf method to find matching dates while populating the calendar in the overriding function of isDisabledDate

var holidays = new Array();
var holidDt = new Date("October 2, 2012");
holidays.push(holidDt.getTime());

Now access the holiday array and check its presence. If present disable, else enable by overriding the isDisabledDate function

isDisabledDate: function(d) {
    var dt = new Date(d);
    var dayN = dt.getDay();
    dt.setHours(0, 0, 0, 0);
    /**
     * Condition for 
     * 1. Weekends
     * 2. Holidays (holiday array needs to be updated with holiday times)
     */
    return ((!((dayN > 0) && (dayN < 6))) || (arrayUtil.indexOf(holidays, dt.getTime()) >= 0));
}

Upvotes: 1

barbossusus
barbossusus

Reputation: 539

AMD style: CalendarLite.js.uncompressed.js in dojo 1.7.1 contains the isDisabledDate function:

isDisabledDate: function(/*===== dateObject, locale =====*/){
    // summary:
    //      May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
    // dateObject: Date
    // locale: String?
    // tags:
    //      extension
/*=====
    return false; // Boolean
=====*/
},
...

You could re-implement the function using this example:

var myCalendar = declare(Calendar, {
    datesToDisable : [],

    constructor: function(args) {
        this.inherited("constructor", arguments);
        this.datesToDisable = args.datesToDisable;
    },

    isDisabledDate: function(/*Date*/date, /*String?*/locale){
        return array.some(this.datesToDisable, function(item) {
            return dojo.compare(item, date, "date") === 0;
        });
    }
});

Then you can use the following constructor and datesToDisable parameter to specify your array.

var someCalendar = new myCalendar({datesToDisable: [new Date(...),....,new Date(....)]},...);

or try this for a fast and dirty solution:

var someCalendar = new Calendar(...);
someCalendar.datesToDisable = [new Date(...),....,new Date(....)];
someCalendar.isDisabledDate = function(/*Date*/date, /*String?*/locale){
        return array.some(this.datesToDisable, function(item) {
            return date.compare(item, date, "date") === 0;
        });
}

But I would recommend the first approach. The assumption is that you know AMD style in order to "import" dijit/Calendar, dojo/_base/array and dojo/date (for "date.compare()" to work).

Cheers!

Upvotes: 1

Alan Kay
Alan Kay

Reputation: 21

I'm making a huge assumption here, that you're populating your array for each month displayed via an XHR request. This XHR request returns an array of strings in Y-m-d format (i.e. ['2011-11-29','2011-11-30']). Another slight assumption is that the XHR request returns an array of dates that should be enabled, but this can be reversed by swapping the disable = true; and disable = false; lines

I don't know how much detail to go into without being patronizing, so if anything is unclear I'll try to clarify afterwards.

dojo.provide("custom.Calendar");
dojo.declare("custom.Calendar", dijit.Calendar, {
    _xhr: null,
    // Month/Year navigation buttons clicked
    _adjustDisplay: function(){
        // Ensure all dates are initially enabled (prevents seepage)
        this.isDisabledDate = function(date) {
            return false;
        };
        this.inherited(arguments);
        this._disableAndPopulate();
    },
    constructor: function(){
        this.inherited(arguments);
        this._disableAndPopulate();
    },
    // Month drop down box
    _onMonthSelect: function(){
        // Ensure all dates are initially enabled (prevents seepage)
        this.isDisabledDate = function(date) {
            return false;
        };
        this.inherited(arguments);
        this._disableAndPopulate();
    },
    // Set disabled dates and re-render calendar
    _disableAndPopulate: function(){
        var currDate = this.currentFocus;

        // Get Lower bound date
        var startDate = new Date();
        startDate.setFullYear(currDate.getFullYear(), currDate.getMonth(), -5);
        // Create ymd dates manually (10x faster than dojo.date.locale.format)
        var startMonth = (startDate.getMonth()<9 ? '0' + (startDate.getMonth()+1) : startDate.getMonth()+1);
        var startDay = (startDate.getDate()<10 ? '0' + startDate.getDate() : startDate.getDate());
        var ymdStartDate = startDate.getFullYear() + '-' + startMonth + '-' + startDay;

        // Get Upper bound date
        var endDate = new Date();
        endDate.setFullYear(currDate.getFullYear(), currDate.getMonth() + 1, 14);
        // Create ymd dates manually (10x faster than dojo.date.locale.format)
        var endMonth = (endDate.getMonth()<9 ? '0' + (endDate.getMonth()+1) : endDate.getMonth()+1);
        var endDay = (endDate.getDate()<10 ? '0' + endDate.getDate() : endDate.getDate());
        var ymdEndDate = endDate.getFullYear() + '-' + endMonth + '-' + endDay;

        var calendar = this;
        // Get IssueDates
        var issueDates;
        // If an existing xhr request is still running, cancel it before starting a new one
        if (this._xhr) {
            this._xhr.cancel();
        }
        this._xhr = dojo.xhrGet({
            url: "http://.....", // url of server-side script
            content: {
                startDate: ymdStartDate, // Earliest possible date displayed on current month
                endDate: ymdEndDate, // Last possible date displayed on current month
                filters: {} // Any additional criteria which your server-side script uses to determine which dates to return
            },
            failOk: true, // Prevent error being logged to console when previous XHR calls are cancelled
            load: function(data){
                issueDates = dojo.fromJson(data);
                if (issueDates === undefined) {
                    // Error with xhr
                } else {
                    calendar.isDisabledDate = function(date) {
                        var disable = true;
                        // Create ymdDate manually (10x faster than dojo.date.locale.format)
                        var month = (date.getMonth()<9 ? '0' + (date.getMonth()+1) : date.getMonth()+1);
                        var day = (date.getDate()<10 ? '0' + date.getDate() : date.getDate());
                        var ymdDate = date.getFullYear() + '-' + month + '-' + day;
                        // Loop through array returned from XHR request, if it contains current date then
                        // current date should not be disabled
                        for (key in issueDates) {
                            if (issueDates[key] == ymdDate) {
                                disable = false;
                                break;
                            }
                        }
                        return disable;
                    };
                    calendar._populateGrid(); // Refresh calendar display
                }
            },
            // Log any errors to console (except when XHR request is cancelled)
            error: function(args) {
                if (args.dojoType == 'cancel') {
                    // Request cancelled
                } else {
                    console.error(args);
                }
            }
        });
    },
    onClose: function() {
        // If an existing xhr request is still running, cancel it before starting a new one
        if (this._xhr) {
            this._xhr.cancel();
        }
    }
});

Upvotes: 2

Related Questions