Apply minTime and maxTime for the current week
I am working in a weekly mode and I want to limit the visible time range to the earliest event of the week and the last event of the week.
I think the correct way to solve the problem is to manually filter the events that are visible in the current week, find the minimum and maximum times and set them to the minTime and maxTime property. The problem is that I don't see the weekChanged callback (or something like that) which seems to be the right place to recalculate minTime and maxTime.
source to share
This was a lot more work than I expected, hope it works well enough for you. I basically do what I suggested in the comments above.
Edit: Changed the code to improve performance, so we don't have to wait for the entire frame to be rendered before knowing we need to start over.
Note that in order to do this more efficiently, we would either have to execute a new callback, because none of the existing ones seem to have set clientEvents already or timed out the events in advance (which can get messy in the case of time zones).
http://jsfiddle.net/3E8nk/555/
(function(c) {
var startedViewRender = true;
function greaterTime(first, second) {
//Assuming dates are the same year
if (first.clone().dayOfYear(0).isBefore(second.clone().dayOfYear(0)))
return second;
else
return first;
}
var calendarOptions = {
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaWeek'
},
defaultView: 'agendaWeek',
minTime: '00:00:00',
maxTime: '24:00:00',
defaultDate: '2014-06-12',
defaultTimedEventDuration: '02:00:00',
editable: true,
events: [{
title: 'All Day Event',
start: '2014-06-01'
}, {
title: 'Long Event',
start: '2014-06-07',
end: '2014-06-10'
}, {
id: 999,
title: 'Repeating Event',
start: '2014-06-09T16:00:00'
}, {
id: 999,
title: 'Repeating Event',
start: '2014-06-16T16:00:00'
}, {
title: 'Meeting',
start: '2014-06-12T10:30:00',
end: '2014-06-12T12:30:00'
}, {
title: 'Lunch',
start: '2014-06-12T12:00:00'
}, {
title: 'Birthday Party',
start: '2014-06-13T07:00:00'
}, {
title: 'Click for Google',
url: 'http://google.com/',
start: '2014-06-28'
}],
viewRender: function(view) {
startedViewRender = true;
},
eventRender: function(event, element, view) {
if (!startedViewRender)
return;
else
startedViewRender = false;
if (view.name !== 'agendaWeek') {
console.log('not agendaWeek');
return;
}
var events = c.fullCalendar('clientEvents');
if (events.length === 0) {
console.log('no events at all');
//Set to default times?
return;
}
var visibleAndNotAllDayEvents = events.filter(function(event) {
//end not necessarily defined
var endIsWithin = event.end ? event.end.isWithin(view.start, view.end) : false;
return !event.allDay && (event.start.isWithin(view.start, view.end) || endIsWithin);
});
if (visibleAndNotAllDayEvents.length === 0) {
console.log('no visible not all day events');
//Set to default times?
return;
}
var earliest = visibleAndNotAllDayEvents.reduce(function(previousValue, event) {
return greaterTime(previousValue, event.start).isSame(previousValue) ? event.start : previousValue;
}, moment('23:59:59', 'HH:mm:ss'));
var latest = visibleAndNotAllDayEvents.reduce(function(previousValue, event) {
var end = event.end ? event.end.clone() : event.start.clone().add(moment(calendarOptions.defaultTimedEventDuration, 'HH:mm:ss'));
return greaterTime(previousValue, end);
}, moment('00:00:00', 'HH:mm:ss'));
if (calendarOptions.minTime !== earliest.format('HH:mm:ss') || calendarOptions.maxTime !== latest.format('HH:mm:ss')) {
//Reinitialize the whole thing
var currentDate = c.fullCalendar('getDate');
c.fullCalendar('destroy');
c.fullCalendar($.extend(calendarOptions, {
defaultDate: currentDate,
minTime: earliest.format('HH:mm:ss'),
maxTime: latest.format('HH:mm:ss')
}));
}
}
};
c.fullCalendar(calendarOptions);
})($('#calendar'));
source to share
You can do this using eventAfterAllRender
which is executed after all events have been displayed
eventAfterAllRender: function(view) {
var evts = $("#calendar").fullCalendar( 'clientEvents'),
minTime = moment("2014-01-01 23:59:59").format("HH:mm:ss"),
maxTime = moment("2014-01-01 00:00:00").format("HH:mm:ss"),
currentDate = view.calendar.getDate(),
currentMinTime = view.calendar.options.minTime,
currentMaxTime = view.calendar.options.maxTime;
// lets calculate minTime and maxTime based on the week events
// if this event minTime is 'before' than the minTime, set this as the minTime
for(var i in evts) {
minTime = timeDiff(minTime, evts[i].start.format("HH:mm:ss"), true);
maxTime = timeDiff(maxTime, evts[i].end.format("HH:mm:ss"), false);
}
// If minTime or maxTime don't match, recreate fullcalendar
// This is a pain in the ass : \
// We have to destroy and apply fullcalendar so this can work.
if (minTime != currentMinTime || maxTime != currentMaxTime) {
$("#calendar").fullCalendar('destroy');
$("#calendar").fullCalendar(
$.extend(fcOpts, {
defaultDate: currentDate,
minTime: minTime,
maxTime: maxTime
})
);
}
}
You should have a function to calculate what time is the most recent or earliest:
function timeDiff(time1, time2, getMin) {
var d1 = new Date('2014-01-01 ' + time1),
d2 = new Date('2014-01-01 ' + time2);
if (getMin) {
return d1.getTime(d1) - d2.getTime(d2) < 0 ? time1 : time2;
} else {
return d1.getTime(d1) - d2.getTime(d2) > 0 ? time1 : time2;
}
}
For a working example see the following JsFiddle .
source to share