在jQuery日期选择器界面上禁用/启用选定日期范围

12

这是我制作的演示http://dev.driz.co.uk/week.html,它展示了一个jQuery UI日期选择器,每个月都有多个实例。

我已经对其进行修改,以便用户选择整个周,并在右侧边栏上存储这些周的开始和结束日期以及周数。

我想要做的是,在用户选择日期后禁用这些日期,以便他们可以在日历选择器中看到哪些日期已被选中(并防止他们添加相同的日期范围超过一次)。

然而我不知道从哪里开始... 我创建了一些启用和禁用日期的函数,但不知道如何使用beforeShowDay方法来实际禁用这些日期。

例如:

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 ]
    }
});

我该如何禁用一段日期范围?因为我只有开始日期和结束日期。并且我能在日期选择器已经在页面上后像我的示例那样调用beforeShowDay吗?然后我该如何重新启用这些日期?

以下是代码:

$(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){


}

简而言之,这里有两个问题...如何在添加日期选择器后禁用日期?其次,如何禁用两个日期之间的范围,因为beforeShowDay方法似乎需要一个日期数组而不是一个范围。


你想避免重复吗? - Padmanathan J
是的,但这应该通过在选定日期时禁用它们来处理,对吗? - Cameron
3个回答

17
但是我如何禁用一段日期范围呢?因为我只有开始和结束日期。一种方法是基于您所拥有的开始和结束日期创建一个日期数组,在beforeShowDay中使用该数组来禁用该范围。 演示: http://jsfiddle.net/abhitalks/FAt66/1/ 例如,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];
}
现在,每当选择日期时,您都可以设置startDateendDate。在上面我提供的示例中,每当在两个顶部输入框中选择一个日期时,开始和结束日期都会被设置。当在第二个输入框中选择日期时,数据数组将被填充。

注意:上面的示例是累加的,即每次选择新范围时,它都会作为禁用日期添加到目标中。如果您想在指定新范围之前清除现有的禁用范围,则可以执行destroy并重新附加日期选择器。(还要重置dateRange数组)

演示2: http://jsfiddle.net/abhitalks/FAt66/3/

相关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];
}

看着你的实际代码,你所需要的只是这个:

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,
    ...

这将持续将新选择的日期范围添加到数组中,并继续进行禁用。但是,请注意,当已选择的星期被删除时,您需要一个逃生路线。在这种情况下,您可以使用多个数组,这些数组可以合并为一个主数组。


好的,我修复了那部分代码,但是当我选择另一个星期时,之前选择的星期就会取消选择... 有什么想法吗? 我在链接中更新了代码。谢谢。 - Cameron
1
您已指定defaultDate为默认日期。 - Abhitalks
1
对于大多数日期范围(除非它们非常小),最好将startDateendDate创建为实际的Date对象,并让beforeShowDay将输入参数与它们进行比较(date > startDate && date < endDate),而不是构建可能包含数百或数千个字符串的数组,通过.datepicker将输入转换为日期,然后再将其转换回字符串,并针对整个数组进行字符串比较。 - brichins
1
@用户:请参考上面brichins的评论。 - Abhitalks
1
@用户:是的。datepicker期望一个三个元素的数组(来自beforeShowDay),第一个是布尔值。其他元素用于指定类等。如果您阅读文档,它将立即变得清晰明了。干杯! - Abhitalks
显示剩余13条评论

0

我尝试了所有的解决方案,但都没有起作用,但我在常见的jquery.datepick.js文件中进行了更改

现有的_isSelectable构造函数

_isSelectable: function(elem, date, onDate, minDate, maxDate) {
        var dateInfo = (typeof onDate === 'boolean' ? {selectable: onDate} :
            (!$.isFunction(onDate) ? {} : onDate.apply(elem, [date, true])));
        //This function is modified by Savata to Block fridays on homepage
        return (dateInfo.selectable !== false) &&
            (!minDate || date.getTime() >= minDate.getTime()) &&
            (!maxDate || date.getTime() <= maxDate.getTime());
    }

已更改为

_isSelectable: function(elem, date, onDate, minDate, maxDate) {
        var dateInfo = (typeof onDate === 'boolean' ? {selectable: onDate} :
            (!$.isFunction(onDate) ? {} : onDate.apply(elem, [date, true])));
        return (dateInfo.selectable !== false) &&
            (!minDate || date.getTime() >= minDate.getTime()) &&
            (!maxDate || date.getTime() <= maxDate.getTime()) && date.getDay() != 5;

/*添加最后一个条件 date.getDay() != 5 来屏蔽星期五 根据您的情况相应更改 星期天是0,星期六是6 */ }


0
如果有一个要求需要禁用一组日期,或者在任何预订类项目中需要在整个过程中禁用某些日期。那么可以使用以下代码:
$(function() {
    //This array containes all the disabled array
      datesToBeDisabled = ["2019-03-25", "2019-03-28"];

        $("#datepicker").datepicker({
          changeMonth: true,
          changeYear: true,
          minDate : 0,
          todayHighlight: 1,
          beforeShowDay: function (date) {
              var dateStr = jQuery.datepicker.formatDate('yy-mm-dd', date);
                  return [datesToBeDisabled.indexOf(dateStr) == -1];
          },

        });
});


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接