jQuery Datepicker beforeShowDay仅在第一次单击后才起作用

时间:2011-05-10 20:03:43

标签: jquery datepicker

我遇到beforeShowDay的问题。

当我加载页面时,直到我点击日历中的某一天,才会突出显示我要突出显示的日期。此外,如果我单击下个月按钮并返回原始月份,则“选定”日期会按预期突出显示。

因此,只有在日历的初始绘制时,日期才会突出显示,因为我已经编程了它们。日历中的任何点击都会自行修复。

我错过了初始选项吗?请参阅下面的代码示例。我的测试网址在受保护的目录中,用户/测试/测试通过。看看右栏底部的迷你卡。切换到下个月,然后回来查看我的问题。请注意5月份突出显示的日期。另请注意,在发生点击之前,“年份”下拉列表也会丢失。

http://www.urbanbands.com/dev/cgi-bin/links/eventmgr.cgi?do=list

代码:

  <script>
$(document).ready(function(){

    // get the current date
    var today = new Date();
    var m = today.getMonth(), d = today.getDate(), y = today.getFullYear();

    // Need list of event dates for THIS month only from database.
    // Declare 'dates' var before adding "beforeShowDay" option to the datepicker,
    // otherwise, highlightDays() does not have the 'dates' array.
    dates = [];
    fetchEventDays(y, m+1);

    $('#datepicker').datepicker({
        dateFormat: 'yy-mm-dd',
        changeMonth: true,
        changeYear: true,
        setDate: today,
        inline: false
    });


    $('#datepicker').datepicker('option', 'onChangeMonthYear', fetchEventDays);
    $('#datepicker').datepicker('option', 'beforeShowDay', highlightDays);
    $('#datepicker').datepicker('option', 'onSelect', getday);


    // ------------------------------------------------------------------
    // getday
    // ------------------------------------------------------------------
    function getday(dateText, inst) { 
        $('#content').load('http://www.mydomain/eventmgr.cgi?do=view_day;date='+dateText+' #eventMgr_content', function() {
    alert('Load was performed. '+dateText);
        });
    }

    // ------------------------------------------------------------------
    // fetchEventDays
    // ------------------------------------------------------------------
    function fetchEventDays(year, month) {
        var paramStr ='?do=get_event_dates&yr=' + year + '&mo=' + month;
        $.get('<%config.db_cgi_url%>/eventmgr-ajax.cgi'+ paramStr, function(data) {
            var recur_dates = data.split(',');
            for(var i = 0; i < recur_dates.length; i++) {
                var date_parts = recur_dates[i].split('-');
                dates.push(new Date(date_parts[0], date_parts[1]-1, date_parts[2]));
            }                       

// This causes dates with events to highlight on initial draw, but
// when clicking to the next month, it switches back to orig month.
//        $('#datepicker').datepicker('option', {}); // Refresh

        });
    }

    // ------------------------------------------------------------------
    // highlightDays
    // ------------------------------------------------------------------
    function highlightDays(date) {
        for (var i = 0; i < dates.length; i++) {
            if ((dates[i].getTime() == date.getTime())) {
                return [true, 'highlight'];
            }
        }
        return [true, ''];
    }


});
  </script>

3 个答案:

答案 0 :(得分:4)

谢谢@kingjiv你是100%正确的。日历在get请求完成之前显示。我尝试使用when方法,但无法异步获取日期。基本上我必须在显示日历之前显示的日期,所以我不得不使用async: false(不是真的)。​​

我已经包含了完整的代码,演示了如何使用beforeShowDay选项突出显示从数据库中提取的多个事件。使用asyc: false修复了突出显示的日期未在初始绘制中突出显示的问题。还包括用于改变细胞背景颜色的css。

还有一个小问题,'年'下拉菜单没有显示在初始绘图上,但我已经确认这只发生在FireFox 4中。任何点击日历都会导致显示年份菜单。 Safari在初始绘图时正确显示年份菜单。

     <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>

<style type="text/css">
/* Dates with events on them. Text color - red, background - pastel yellow. */
td.highlight, table.ui-datepicker-calendar tbody td.highlight a { 
    background: none !important;
    background-color: #fffac2 !important; 
    color: #FF0000;
}

/* This is Today's day in rightsidebar mini calendar (datepicker). */
/* Restore style to that of a default day, then just bold it. */
.ui-state-highlight, .ui-widget-content .ui-state-highlight {
    border: 1px solid #d3d3d3; 
    background: #e6e6e6 url(http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; 
    font-weight: bold;
    color: #555555;
}

/* This is the selected day in the inline datepicker. */
.ui-state-active, .ui-widget-content .ui-state-active {
    color: #000000;
    opacity: 1.0;
    filter:Alpha(Opacity=100);
    border: 1px solid #000000;
}

/* Add a little separation between month and year select menus */
.ui-datepicker select.ui-datepicker-month {
    width: 42%;
    margin-right: 6px;
}

</style>

<script>
$(document).ready(function(){

    // get the current date
    var today = new Date();
    var m = today.getMonth(), d = today.getDate(), y = today.getFullYear();

    // Get a list of dates that contain events in THIS month only from database.
    // Declare and populate 'eventDates' array BEFORE adding "beforeShowDay" option to 
    // the datepicker. Otherwise, highlightDays() will have an empty 'eventDates' array.

    var eventDates = [];
    fetchEventDays(y, m+1);     // Get events for the current year and month.

    $('#datepicker').datepicker();
    $('#datepicker').datepicker('option', 'onChangeMonthYear', fetchEventDays);
    $('#datepicker').datepicker('option', 'beforeShowDay', highlightDays);
    $('#datepicker').datepicker('option', 'onSelect', getday);
    $('#datepicker').datepicker('option', 'dateFormat', 'yy-mm-dd');
    $('#datepicker').datepicker('option', 'changeYear', true);
    $('#datepicker').datepicker('option', 'changeMonth', true);
    $('#datepicker').datepicker('option', 'yearRange', '2010:2012');
    $('#datepicker').datepicker('option', 'showButtonPanel', true);

    // Disable all dates prior to today.
    //  $('#datepicker').datepicker('option', 'minDate', new Date(y, m, d));

    // ------------------------------------------------------------------
    // getday - Replaces the #content div of the current page with 
    // the content of the page that is created and displayed via perl
    // ------------------------------------------------------------------
    function getday(dateText, inst) { 
        $('#content').load('<%config.db_cgi_url%>/eventmgr.cgi?do=view_day;date='+dateText+' #eventMgr_content', function() {
//      alert('load was performed. '+dateText);
        });
    }

    // ------------------------------------------------------------------
    // fetchEventDays - The ajax call below is synchronous (NOT asynchronous).
    // eventDates array must be populated prior to adding the beforeShowDay option
    // to the datepicker, otherwise, highlightDays() will have an empty eventDates array.
    // ------------------------------------------------------------------
    function fetchEventDays(year, month, inst) {
        var url ='<%config.db_cgi_url%>/eventmgr-ajax.cgi?do=get_event_dates&yr=' + year + '&mo=' + month;

        $.ajax({
            url: url,
            async: false,
            success: function(result){
                var event_dates = result.split(',');
                for(var i = 0; i < event_dates.length; i++) {
                    var date_parts = event_dates[i].split('-');
                    eventDates.push(new Date(date_parts[0], date_parts[1]-1, date_parts[2]));
                }                       
            }
        });
    }

    // ------------------------------------------------------------------
    // highlightDays - Add a custom css class to dates that exist in the
    // eventDates array. Must also add the css for td.highlight (above).
    // ------------------------------------------------------------------
    function highlightDays(date) {
        for (var i = 0; i < eventDates.length; i++) {
            if ((eventDates[i].getTime() == date.getTime())) {
                return [true, 'highlight'];
            }
        }
        return [true, ''];
    }

});
</script>

答案 1 :(得分:3)

我无法看到jQuery.when将如何提供帮助(看起来它不会推迟日期选择器中的事件)但是我设法通过禁用选择器来避免async = false,然后在收到数据时刷新ajax回调

var available_days = [];

var data = get_selected();
var today = new Date();
data['year'] = today.getFullYear();
data['month'] = today.getMonth() + 1;
$.get('{% url views.get_availability %}', data,
    function(get_data) {
        $("#datepicker").datepicker("destroy");
        available_days = get_data['available_days'];
        $("#datepicker").datepicker({
            onChangeMonthYear: function(year, month, inst) {
                 $("#datepicker").datepicker("disable");
                 available_days = [];
                 data['year'] = year;
                 data['month'] = month;
                 $.get('{% url views.get_availability %}', data,
                     function(get_data) {
                         available_days = get_data["available_days"];
                         $("#datepicker").datepicker("refresh");
                         $("#datepicker").datepicker("enable");
                     }
                 );
             },            
             beforeShowDay: function(date) {
                return [$.inArray(date.getDate(), available_days) >= 0, ''];
             },
             onSelect: function(dateText, inst) { showTimes(dateText, data); },
             dateFormat: "dd-mm-yy",
         });
     }
);

答案 2 :(得分:1)

我看不到您的示例,因为系统会提示您输入用户名和密码。但是,请参阅下面我认为正在发生的事情。

$.get只是制作AJAX get请求的简写。 AJAX是异步的,意味着你调用它并且它不等待响应。所以基本上,可能发生的是在获取请求完成之前显示日历。

我可以通过两种方式解决这个问题。一种方法是将你的get转换为完整的ajax调用并设置async : true

http://api.jquery.com/jQuery.ajax/

另一种选择(可能是更好的选择)是使用whenWhen基本上允许您在执行任何其他操作之前等待ajax请求完成。这允许它仍然是异步的,但确保不会过早地执行依赖代码。这样,可以在ajax调用和依赖代码之间执行其他操作。

http://api.jquery.com/jQuery.when/