Custom three day view problems - fullcalendar

I'm trying to adapt fullcalendar to fit a smaller screen (iPhone) and I am trying to create a useful week view by displaying 3 days instead of 7. It is an easy modification to change the columns displayed to 3 days but this causes issues when rendering events. Nothing shows up on the correct day!
Here is the modified source code:
function BasicWeekView(element, calendar) {
...
function render(date, delta) {
if (delta) {
addDays(date, delta * 3);
}
var start = addDays(cloneDate(date), 3);
var end = addDays(cloneDate(start), 3);
var visStart = cloneDate(start);
var visEnd = cloneDate(end);
t.title = formatDates(
visStart,
addDays(cloneDate(visEnd), -1),
opt('titleFormat')
);
t.start = start;
t.end = end;
t.visStart = visStart;
t.visEnd = visEnd;
renderBasic(1, 1, 3, false);
}
}
This causes the events to render incorrectly and I'm mystified as to why? I've gone through the source and tried to trace it back to the cause without success. Clicking the day still shows the proper date (via dayClick) so I am out of ideas.
To give a bit more detail on the errors, almost every event renders incorrectly. The third day will often render events in the first day or not at all (ie 1px wide). The second day renders events in the third day and the first in the second. Weekends are handled strangely as well and sometimes when moving to the next date or previous date it will change to day view.
I'm completely baffled and would love some help. I have dug through the api and trolled through the questions on stack exchange without luck... any help would be appreciated :)

I was looking to do something similar with Full Calendar on Android.
There was an update in version 2.2.5 of Full Calendar that allows this kind of customization.
This can now be done with something like this:
views: {
agendaThreeDay: {
type: 'agenda',
duration: { days: 3 },
buttonText: '3 day'
},
defaultView: 'agendaThreeDay'
}
Customizing full calendar can still be a nightmare but it's come a long way.
You can get more information on this from the document page on Custom Views.

Related

FullCalendar - selectOverlap prevents creation of allday events

Because selectOverlap function only passes through the event being overlapped, and not the selection, it is difficult to customise how to handle event creation.
In my case, we are working on a calendar/diary system, with background events showing the employee's shifts, and events showing their individual bookings.
At this point, other than the background events - absolutely no events should be able to overlap each other.
However... on top of that - we are then overlaying 'all day events' - which might be any number of things, but for examples sake, let's say they're 'staff birthdays' - therefore, you might have a couple of events today, but there will be an event in the all day section, showing someone's birthday.
I am checking for eventOverlap and doing some other checks on eventDrop and eventResize which handle different clashes, but these only work for existing events being moved or resized. I would like to do the same on event creation - which happens during the select. In order to disallow the select of spaces which already have events, I am using the example function from the selectOverlap documentation:
function(event) {
return event.rendering === 'background';
}
This works fantastically. However, if I try to create a new All Day event, it will 'overlap' any other events that exist on that day, and not pass this check.
I was hoping to be able to use the selection's object to check it for an allDay=true, but the function is only passed the existing event, and there is no way to check the selected section.
You can see a very simplified demo here:
https://codepen.io/anon/pen/NQrxOO
Try to create an allday event on the day which already has events.
Is there a better way to do this? I can completely remove the selectOverlap and do everything in the select callback instead, but I would need to essentially duplicate the overlap checks just to make this work, and I feel like that seems like overkill for something that should be relatively simple.
Is it possible to get not only the overlapped event object, but also the selection object when doing a selectOverlap function?
Current workaround is to remove the selectOverlap check, and instead do it myself within the select callback.
Below is a simplified version of a quick function I wrote to call when using select={this.handleEventCreate}:
class Diary extends React.Component {
//additional functions, state definitions, etc etc etc here.
//Define calendarRef as it will be needed in the function below
calendarRef = React.createRef();
handleEventCreate = (info) => {
// Get the Calendar API to allow unselection
let calendarApi = this.calendarRef.current.getApi();
// Get all Events
let checkEvents = calendarApi.getEvents();
// Loop through them
checkEvents.forEach(function(event){
// If it's not a background element, check whether the new element contains the existing, or vice versa.
if(event.rendering !== "inverse-background" &&
(
(event.start >= info.start && event.start <= info.end) ||
(event.end >= info.start && event.end <= info.end) ||
(info.start >= event.start && info.start <= event.end) ||
(info.end >= event.start && info.end <= event.end)
)
){
// It is an overlapping event, so we reject it.
return calendarApi.unselect();
}
});
alert('All good here to create the event.');
//extra event creation code to fire here.
}

Fullcalendar permit selectOverlap for one day

I'm using Fullcalendar and I need to allow event overlap for one day: the last still event day can overlap on the first new event day.
For resizing and drop I resolved in this way:
eventOverlap: function(stillEvent, movingEvent) {
var a = movingEvent.start.startOf('day');
var b = stillEvent.end.startOf('day');
if(a.unix() == b.unix()){
return true;
}
return false;
}
Now I need to do the same on selecting, according to documentation, I have to use selectOverlap option by define a function, but differently of eventOverlap, this function not have an argument that include the current selection period, then I don't know how to make the check.
Somebody can say me how to do so?
UPDATE 19/05/2017:
I opened an issue on github's project repository here

Fullcalendar: getting "Va.time is undefined" when trying to assign a moment to event.end

I'm using FullCalendar and it is working fine.
I allow users to drag events, but sometimes I need to force the event to start on a specific date. For example, some events MUST start on a Monday, so if a user drags it to a different weekday, I'll force the event move to the previous Monday.
So, on the eventDrop callback, I have something like:
jQuery('#calendar').fullCalendar({
...
...
eventDrop: function(event, delta, revertFunc) {
if (/*must force new event start date*/) {
var duration = event.end.diff(event.start, 'd');
event.start = moment('2015-07-01');
event.end = moment('2015-07-01').add(duration, 'd');
}
}
})
Some explaining:
I must calculate the original duration, because when I change the
start date, Fullcalendar assumes the end date is the same and changes
the event duration accordingly. So it forces me to assign a new end
date (is there another way to do this?)
assigning a new date to event.start works fine
assigning a new date to event.end always returns:
TypeError: Va.time is undefined
Am I missing something, or maybe overcomplicating things?
Is the error a bug?
Thanks in advance for helping me on this!
Just modify the existing moment like this:
eventDrop: function (event) {
event.start.day(1); //Move the startdate to day 1 (Monday, 0 = Sunday)
event.end.day(1); //Also move the enddate to Monday
}
jsFiddle
I'm not sure what causes the error. It looks like it has to be something to do with setting a new momentjs object in either the event.start or event.end.

Meteor setInterval stacking

I am using Meteor.setInterval to count up to keep track of a players "action points" in a game. When they use an action (like attacking), it will decrease the amount. However, when an event is triggered(attacking) it updates players profile on my DB which triggers the setInterval to stack each time the DB is updated. It starts to counter faster and faster. edit This is the issue. I don't want it to count faster. I want only one interval to be running.
This was the closest solution I could find:
prevent javascript setInterval function stacking up
Didn't quite work and I couldn't find a different way to arrange the flags to only have one setInterval going.
Heres my helper: Each player has a different regen which is pulled from their profile. I've substituted fixed numbers for the interval and did a Session.get() when the stacking occurs, it stays the same. Instead of numbers I was just adding 'x' so it looks like a loading bar.
apTicker:function() {
Session.set('apRegen', Meteor.user().profile.apRegen);
Meteor.setInterval(function () {
if (Session.get('ap').length < 25) {
Session.set('ap', Session.get('ap')+"x");
}
}, Session.get('apRegen'))
},
Thank you.
This should do what you want:
var apTickerInterval; //To keep track of the interval
Session.set('apRegen', Meteor.user().profile.apRegen);
//...
apTicker : function()
{
if(apTickerInterval)
Meteor.clearInterval(apTickerInterval);
apTickerInterval = Meteor.setInterval(function () {
if (Session.get('ap').length < 25) {
Session.set('ap', Session.get('ap')+"x");
}
}, Session.get('apRegen'));
}

FullCalendar passing starting date

Can someone help me understand how I can pass the start date into the calendar. I have created a Delivery Scheduler calendar and I display the delivery details in a table under the calends that is feed via the database. This requires me to refresh the page when a user select a calendar day to load the table information. I can figure out how to start the calendar on a starting date that is passed into the page.
Seems like this would be easy but I am doing something wrong.
$('#calendar').fullCalendar(Options);
$('#calendar').fullCalendar('gotoDate', '2012-10-21');
Sample based on documentation http://arshaw.com/fullcalendar/docs/current_date/gotoDate/
Remember that month is 0-based, so 10 means November.
$(document).ready(function () {
var calendar = $('#calendar').fullCalendar({
events:[
{ title:'All Day Event', start:new Date(2012, 10, 20)},
{ title:'Long Event', start:new Date(2012, 10, 21), end:new Date(2012, 10, 22)}
]
});
$('#calendar').fullCalendar('gotoDate', 2012, 10, 21);
});
Thank you Biesior for your helpful answer. I was able to use your suggested code to get the behavior I was looking for.
While using the approach above, I notice that Firebug's console shows two AJAX data requests being executed simultaneously, one for the view associated with the current date, and one for the view associated with the specified gotoDate.
There doesn't appear to be any additional delay from the user's perspective, and the calendar displays the requested view from the start. However, 'loading' callbacks will be called multiple times which might cause strange behavior in certain circumstances. There may also be other undesired results associated with the superfluous AJAX request for the current date.
I was able to avoid the unnecessary AJAX request by initializing the calendar without an event source, then moving to the desired date as shown by Biesior above, and then adding the event source. The sequence is shown below. I've removed some unrelated FullCalendar options and callbacks to keep it concise. There are some additional AJAX parameters, and some PHP, but the important thing to notice is when the event source is specified.
The original code results in two simultaneous AJAX requests:
$('#calendar').fullCalendar({
events: {
url:'/Services/GetEvents.php',
type: 'POST',
data: {
lat: <?=$venLatitude?>,
lon: <?=$venLongitude?>,
userID: <?=$userID?>,
distance: <?=$distance?>
}
}
})
$('#calendar').fullCalendar('gotoDate', <?=(int)substr($startDate,0,4)?>, <?=((int)substr($startDate,5,2))-1?>);
This adjustment results in only the desired AJAX request:
$('#calendar').fullCalendar();
$('#calendar').fullCalendar('gotoDate', <?=(int)substr($startDate,0,4)?>, <?=((int)substr($startDate,5,2))-1?>);
$('#calendar').fullCalendar('addEventSource', {
url:'/Services/GetEvents.php',
type: 'POST',
data: {
lat: <?=$venLatitude?>,
lon: <?=$venLongitude?>,
userID: <?=$userID?>,
distance: <?=$distance?>
}
});

Resources