Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable/Enable selected date range on jQuery datepicker UI

So I have the following demo http://dev.driz.co.uk/week.html that shows a jQuery UI datepicker that has multiple instances for each month of the year.

I've modified it so that the user selects entire weeks and then start and end dates for those weeks are stored on the right hand sidebar with a week number.

What I want to do is disable the dates once the user has selected them so they can see on the calender picker what dates have been selected (and also prevent them from adding the same date range more than once).

However I don't know where to start with this... I've created some enable and disable date functions but don't know how to actually disable the dates using the beforeShowDay method.

For example:

var array = ["2013-03-14","2013-03-15","2013-03-16"]

$('.week-picker').datepicker({
    beforeShowDay: function(date){
        var string = jQuery.datepicker.formatDate('yy-mm-dd', date);
        return [ array.indexOf(string) == -1 ]
    }
});

But how would I disable a range of dates? As I only have the start and end dates. And can I call the beforeShowDay AFTER the datepicker is on the page like in my example? AND how can I then re-enable the dates?

Here's the code:

$(function() {

    var startDate;
    var endDate;

    var selectCurrentWeek = function() {
        window.setTimeout(function () {
            $('.week-picker').find('.ui-datepicker-current-day a').addClass('ui-state-active');
        }, 1);
    }

    $('.week-picker').datepicker( {
        defaultDate: '01/01/2014',
        minDate: '01/01/2013',
        maxDate: '01/01/2015',
        changeMonth: false,
        changeYear: true,
        showWeek: true,
        showOtherMonths: true,
        selectOtherMonths: true,
        numberOfMonths: 12,
        onSelect: function(dateText, inst) { 
            var date = $(this).datepicker('getDate');
            startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay());
            endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay() + 6);
            var dateFormat = inst.settings.dateFormat || $.datepicker._defaults.dateFormat;

            addWeek($.datepicker.iso8601Week(new Date(dateText)), $.datepicker.formatDate( dateFormat, startDate, inst.settings ), $.datepicker.formatDate( dateFormat, endDate, inst.settings ));

            disableDates( $.datepicker.formatDate( dateFormat, startDate, inst.settings ), $.datepicker.formatDate( dateFormat, endDate, inst.settings ));

            selectCurrentWeek();
        },
        beforeShowDay: function(date) {
            var cssClass = '';
            if(date >= startDate && date <= endDate)
                cssClass = 'ui-datepicker-current-day';
            return [true, cssClass];
        },
        onChangeMonthYear: function(year, month, inst) {
            selectCurrentWeek();
        }
    });

    $('.week-picker .ui-datepicker-calendar tr').live('mousemove', function() { $(this).find('td a').addClass('ui-state-hover'); });
    $('.week-picker .ui-datepicker-calendar tr').live('mouseleave', function() { $(this).find('td a').removeClass('ui-state-hover'); });

    $('.remove').live('click', function(e){

        enableDates($(this).attr('data-startdate'), $(this).attr('data-enddate'));

        $(this).parent('div').remove();
    });

});

// adds the week to the sidebar
function addWeek(weekNum, startDate, endDate){

    $('.weeks-chosen').append('<div data-startdate="'+startDate+'" data-enddate="'+endDate+'"><span class="weekNum">Week '+ (weekNum - 1) +'</span> - <span class="startDate">'+startDate+'</span> - <span class="endDate">'+endDate+'</span> | <span class="remove">X Remove</span></div>');

}

// disable the dates on the calendar
function disableDates(startDate, endDate){


}

// enable the dates on the calendar
function enableDates(startDate, endDate){


}

In short there are two questions here... How do I disable dates AFTER the datepicker is added to the page. And second how do I disable a range between two dates, as it looks like the beforeShowDay method expects an array of dates rather than a range.

like image 824
Cameron Avatar asked Jun 30 '14 09:06

Cameron


People also ask

How do I disable date range picker?

DateRangePicker can be inactivated on a page, by setting enabled value as false that will disable the component completely from all the user interactions including in form post.

How do I enable only certain dates in datepicker?

Answers. To achieve this function, you can use beforeShowDay in the datepicker to do it.

How can I hide datepicker after selecting date in jQuery?

Syntax: $(". selector"). datepicker("hide");

How do I disable UI datepicker trigger?

Datepicker has a built-in disable method for this you can use, which also disables the text input, like this: $("#datepicker"). datepicker("disable");


1 Answers

But how would I disable a range of dates? As I only have the start and end dates.

One way could be to create an array of dates based on the start and end dates that you have. Use that array in beforeShowDay to disable the range.

Demo: http://jsfiddle.net/abhitalks/FAt66/1/

For example, Relevant portions of JS:

var startDate = "2014-06-15", // some start date
    endDate  = "2014-06-21",  // some end date
    dateRange = [];           // array to hold the range

// populate the array
for (var d = new Date(startDate); d <= new Date(endDate); d.setDate(d.getDate() + 1)) {
    dateRange.push($.datepicker.formatDate('yy-mm-dd', d));
}

// use this array 
beforeShowDay: function (date) {
    var dateString = jQuery.datepicker.formatDate('yy-mm-dd', date);
    return [dateRange.indexOf(dateString) == -1];
}

Now, you could set startDate and endDate whenever a date is selected. In the example fiddle I linked to above, the start and end dates are set whenever a date is selected in the two top inputs. The data array is populated when date is selected in the second input.

Note: The above example is additive, i.e. everytime you select a new range it gets added as disabled dates into the target. If you want to clear the existing disabled range before specifying a new range, then you could do a destroy and reattach the datepicker. (And also reset the dateRange array)

Demo 2: http://jsfiddle.net/abhitalks/FAt66/3/

Relevant portion of JS:

$("#dt").datepicker("destroy");
$("#dt").datepicker({ 
    dateFormat : 'yy-mm-dd',
    beforeShowDay: disableDates
});

var disableDates = function(dt) {
    var dateString = jQuery.datepicker.formatDate('yy-mm-dd', dt);
    return [dateRange.indexOf(dateString) == -1];
}

Looking at your actual code, all you need is this:

onSelect: function(dateText, inst) { 
    var date = $(this).datepicker('getDate');
    startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay());
    endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay() + 6);
    var dateFormat = inst.settings.dateFormat || $.datepicker._defaults.dateFormat;

    addWeek($.datepicker.iso8601Week(new Date(dateText)), $.datepicker.formatDate( dateFormat, startDate, inst.settings ), $.datepicker.formatDate( dateFormat, endDate, inst.settings ));

    for (var d = new Date(startDate);
        d <= new Date(endDate);
        d.setDate(d.getDate() + 1)) {
            dateRange.push($.datepicker.formatDate('dd/mm/yyyy', d));
    }

    selectCurrentWeek();
},
beforeShowDay: disableDates,
    ...

This will keep adding the newly selected date ranges to the array and will additively keep on disabling. But, be cautioned that you will need an escape route when an already selected week is removed. In that case, you may work with multiple array which can be coalesced into one master array.

like image 120
Abhitalks Avatar answered Sep 20 '22 19:09

Abhitalks