I'm having a problem with beforeShowDay
.
When my page loads, the days I've told to highlight are not highlighted until I click a day in the calendar. Also if I click the next-month button and come back to the original month, then the 'selected' days are highlighted as expected.
So, only on the initial draw of the calendar do the dates not highlight as I have programmed them to do. Any click in the calendar fixes itself.
Am I missing an init option? Please see my code example below. My test url is in protected directory with a user/pass of test/test. Look at the mini-cal in right column bottom. Switch to the next month and back to see my problem. Note the highlighted days im May. Also, note that the 'year' dropdown also is missing until a click happens.
http://www.urbanbands.com/dev/cgi-bin/links/eventmgr.cgi?do=list
The code:
<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>
Thanks @kingjiv You were 100% correct. The calendar was displaying before the get request completed. I tried using the when
method, but could not get the dates asynchronously. Basically I must have the the dates to highlight before the calendar is displayed, so I had to use async: false
(not true).
I've included my complete code which demonstrates how to highlight multiple events pulled from a database using the beforeShowDay
option. Using asyc: false
fixed the issue where the highlighted dates did not highlight on the initial draw. The css for changing the cells background color is included as well.
There is still a tiny issue where the 'year' dropdown menu does not display on the initial draw, but I have confirmed that this only happens in FireFox 4. Any click on the calendar causes the year menu to display. Safari properly displays the year menu on initial draw.
<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>
I couldn't see how jQuery.when would help (it doesn't look like it would defer events from the date picker) but I managed to avoid async=false by disabling the picker then refreshing when data is received in the ajax callback
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",
});
}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With