FullCalendar showing Duplicates Events on Month change - javascript

I am working on adding events to fullcalendar with Javascript. I am using fullcalendar-2.7.2. The events are added when i click on the custom button but when I change the month it shows many duplicate events.
Here is the code that I have written :-
<script>
$(document).ready(function() {
$('#calendar').fullCalendar({
theme: true,
eventClick: function(event) {
// opens events in a popup window
window.open(event.url, 'gcalevent', 'width=700,height=600');
return false;
},
loading: function(bool) {
$('#processingDiv').toggle(bool);
},
selectable: true,
selectHelper: true,
select: function(start, end) {
var title = prompt('Event Title:');
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
}
$('#calendar').fullCalendar('unselect');
},
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
defaultDate: moment().utc().valueOf(),
editable: true,
eventLimit: true, // allow "more" link when too many events
fixedWeekCount: false
});
try {
//This data is showing Okay. This one is the Test Event in image Below on Date 1.
var jsonStart = JSON.parse('{!jsonStringSF}');
var myCalendar = $('#calendar');
for(var i=0; i < jsonStart.length; i++) {
var myEvent = {
id: jsonStart[i].id,
title: jsonStart[i].title,
allDay: jsonStart[i].allDay,
start: jsonStart[i].startDate,
end: jsonStart[i].endDate
};
myCalendar.fullCalendar('removeEvents', myEvent.id );
myCalendar.fullCalendar( 'renderEvent', myEvent, true );
}
} catch(err) {
alert(err.message);
}
});
</script>
<body>
<apex:form >
<apex:actionFunction name="getEventsFromGoogle" action="{!getEventsFromCalendar}" onComplete="showEventsOnCalendar('{!jsonString}');" />
<apex:actionFunction name="syncEventsToGoogle" action="{!startSyncToGoogle}" onComplete="hideProcessingDiv();" />
</apex:form>
<div id="processingDiv" style="display:none;">
<apex:outputPanel styleClass="popupBackground" layout="block"/>
<apex:outputPanel styleClass="custPopup" layout="block">
<img src="/img/loading24.gif" style="vertical-align:middle; horizontal-align:middle"/>
<span>Please wait...</span>
</apex:outputPanel>
</div>
<div id="allButtons">
<button class="ui-button ui-state-default" onClick="syncToGoogle();">Sync Salesforce to Google</button>
<button class="ui-button ui-state-default" onclick="connectToGoogle();">Sync Google to Salesforce</button>
</div>
<div id='calendar'></div>
<script>
function syncToGoogle() {
showProcessingDiv();
syncEventsToGoogle();
}
function connectToGoogle() {
showProcessingDiv();
getEventsFromGoogle();
}
function showEventsOnCalendar(jsonString) {
//jsonString is [{"title":"Assign Task","startDate":"2016-05-07T13:00:00+05:30","sequence":1,"recurrence":["RRULE:FREQ=WEEKLY;BYDAY=SU,SA"],"id":"mhpufelkfo1d7thn2naqm2s2ec","endDate":"2016-05-07T14:00:00+05:30","allDay":false}]
try {
var json = JSON.parse(jsonString); //This is String which has list of events.
var myCalendar = $('#calendar');
var myEvent = '';
for(var i=0; i < 1; i++) { //For testing I have itrated the loop just once.
myEvent = '';
var recurValue = JSON.stringify(json[i].recurrence);
//RRULE:FREQ=WEEKLY;UNTIL=20160520T110000Z;BYDAY=MO,TU,WE,TH,FR,SU,SA
//Recurrence returns this format.
if(recurValue != null && recurValue != 'null') {
var Frequency = recurValue.match("FREQ=(.*?);");
var Until = recurValue.match("UNTIL=(.*?);");
var ByDay = recurValue.match("BYDAY=(.*?)\"]");
if(ByDay[1] == null && ByDay[1] == 'null') {
ByDay[1] = '';
}
var repeatDays = [];
if(ByDay[1].indexOf('MO') > -1) {
repeatDays.push(1);
}
if(ByDay[1].indexOf('TU') > -1) {
repeatDays.push(2);
}
if(ByDay[1].indexOf('WE') > -1) {
repeatDays.push(3);
}
if(ByDay[1].indexOf('TH') > -1) {
repeatDays.push(4);
}
if(ByDay[1].indexOf('FR') > -1) {
repeatDays.push(5);
}
if(ByDay[1].indexOf('SA') > -1) {
repeatDays.push(6);
}
if(ByDay[1].indexOf('SU') > -1) {
repeatDays.push(0);
}
myEvent = {
id: json[i].id,
title: json[i].title,
allDay: json[i].allDay,
start: json[i].startDate,
end: json[i].endDate,
dow: repeatDays
};
} else {
myEvent = {
id: json[i].id,
title: json[i].title,
allDay: json[i].allDay,
start: json[i].startDate,
end: json[i].endDate
};
}
$('.fc-event').remove(); //Tried this is solve the problem but failed.
//myCalendar.fullCalendar('removeEvents', myEvent.id ); //also tried this but still no luck.
myCalendar.fullCalendar( 'renderEvent', myEvent, true );
}
hideProcessingDiv();
} catch(err) {
hideProcessingDiv();
alert(err.message);
}
}
This is how it looks at start :-
Here is the screenshot of the problem when click on the next month or come back: -
Can anyone suggest me the solution to stop the duplicates?

Related

How can I set time limit in calendar?

I am using https://ui.toast.com/tui-calendar Toast Calender I just want show 09:00-17:00 in this calendar. It works on my PC but it shows me full time,
but It doesn't have options for limit.
this calendar can not set custom limit times?
Script
const week = {
hourStart: 9,
hourEnd: 17
};
var Calendar = tui.Calendar;
var calendar = new Calendar('#calendar', {
defaultView: 'week',
taskView: false,
useCreationPopup: false,
useDetailPopup: true,
allDaySlot: false,
droppable: false,
template: {
monthDayname: function(dayname) {
return '<span class="calendar-week-dayname-name">' + dayname.label + '</span>';
}
}
});
document.getElementById('my-today-button').addEventListener('click', function() {
calendar.today();
});
document.getElementById('my-next-button').addEventListener('click', function() {
calendar.next();
});
document.getElementById('my-prev-button').addEventListener('click', function() {
calendar.prev();
});
document.getElementById('weekView').addEventListener('click', function() {
calendar.changeView('week', true);
});
document.getElementById('monthView').addEventListener('click', function() {
calendar.changeView('month', true);
});

why addEvent from Fullcalendar does not work

Hi I am following the https://fullcalendar.io/ v4 to build my js calendar. I try to crate a new event by clicking on the calendar then call the function addEvent. where and how can I call the function addEvent can you put an example please ? I have the same question about remove an event. here is what I did, for each click I addd an event, just to see if it works. It does not work.
var event1 = [
{
title: 'MyEvent',
start: '2020-03-03T13:00:00',
end:'2020-03-03T14:00:00'
},
]
var calendar = new FullCalendar.Calendar(calendarEl, {
eventClick: function (info) {
calendar.addEvent( event1)
},
plugins: ["interaction", "timeGrid"],
header: {
left: "prev,next today",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay,listMonth",
},
defaultDate: currentDate,
navLinks: true,
businessHours: {
startTime: "08:00",
endTime: "18:00",
},
editable: true,
weekends: false,
allDaySlot: false,
locale: "en",
events:
[
{
title: 'MyEvent',
start: '2020-03-03T13:00:00',
end:'2020-03-03T14:00:00'
},
]
});
calendar.render();
I looked at the function addEvent from main.js, it looks like id did nothing , tuple got nul and the function (addEvent) returns nul as well !
Calendar.prototype.addEvent = function (eventInput, sourceInput) {
if (eventInput instanceof EventApi) {
var def = eventInput._def;
var instance = eventInput._instance;
// not already present? don't want to add an old snapshot
if (!this.state.eventStore.defs[def.defId]) {
this.dispatch({
type: 'ADD_EVENTS',
eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args?
});
}
return eventInput;
}
var sourceId;
if (sourceInput instanceof EventSourceApi) {
sourceId = sourceInput.internalEventSource.sourceId;
}
else if (sourceInput != null) {
var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
if (!sourceApi) {
console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test
return null;
}
else {
sourceId = sourceApi.internalEventSource.sourceId;
}
}
var tuple = parseEvent(eventInput, sourceId, this);
if (tuple) {
this.dispatch({
type: 'ADD_EVENTS',
eventStore: eventTupleToStore(tuple)
});
return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
}
return null;
};
Do you have any example on how to use addEvent function
Your problem here is that event1 is an array, not an object. The addEvent function expects a single object as input, not a list / array.
Change it to a plain object:
var event1 =
{
title: 'MyEvent',
start: '2020-03-03T13:00:00',
end:'2020-03-03T14:00:00'
}
(without the [ and ] which wrap the object inside an array) and your original code should work fine.
Well, I took the example from the fullcalendar site, and it works:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>
Add an event dynamically - Demos | FullCalendar
</title>
<link href='/assets/demo-to-codepen.css' rel='stylesheet' />
<style>
html, body {
margin: 0;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 900px;
margin: 40px auto;
}
</style>
<link href='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.css' rel='stylesheet' />
<link href='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.css' rel='stylesheet' />
<script src='/assets/demo-to-codepen.js'></script>
<script src='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'dayGrid' ],
defaultView: 'dayGridMonth',
header: {
center: 'addEventButton'
},
customButtons: {
addEventButton: {
text: 'add event...',
click: function() {
var dateStr = prompt('Enter a date in YYYY-MM-DD format');
var date = new Date(dateStr + 'T00:00:00'); // will be in local time
if (!isNaN(date.valueOf())) { // valid?
calendar.addEvent({
title: 'dynamic event',
start: date,
allDay: true
});
alert('Great. Now, update your database...');
} else {
alert('Invalid date.');
}
}
}
}
});
calendar.render();
});
</script>
</head>
<body>
<div class='demo-topbar'>
<button data-codepen class='codepen-button'>Edit in CodePen</button>
Click the "add event..." button
</div>
<div id='calendar'></div>
</body>
</html>

Fullcalendar: Unable to resize repeating events that use ranges[]

I am currently creating a calendar that will display repeating classes for a student for a university project. I am able to display the repeating events on the calendar, but whenever I attempt to resize or drag and drop an event I am getting the following errors in the browser web console:
TypeError: this.eventInstances[0] is undefined [Learn More] fullcalendar.min.js:6:26715
TypeError: t is undefined [Learn More] fullcalendar.min.js:8:6813
This is the JSON being passed into the calendar:
[{"id":22,"title":"Class: CSC3047\n Location: DKB","start":"12:00","end":"14:00",
"allDay":false,"description":"Mr Jack Dell","dow":[1],"ranges":[{"start":"2018-03-12",
"end":"2018-10-15"}]},{"id":23,"title":"Class: CSC3056\n Location: Ashby","start":"09:00",
"end":"11:00","allDay":false,"description":"Narelle Allen","dow":[3],
"ranges":[{"start":"2018-03-12","end":"2018-10-15"}]}]
This is the javascript I am using to display/edit/update the calendar events:
var currentUpdateEvent;
var addStartDate;
var addEndDate;
var globalAllDay;
function updateEvent(event, element) {
//alert(event.description);
if ($(this).data("qtip")) $(this).qtip("destroy");
currentUpdateEvent = event;
$('#updatedialog').dialog('open');
$("#eventName").val(event.title);
$("#eventDesc").val(event.description);
$("#eventId").val(event.id);
$("#eventStart").text("" + event.start.toLocaleString());
if (event.end === null) {
$("#eventEnd").text("");
}
else {
$("#eventEnd").text("" + event.end.toLocaleString());
}
}
function updateSuccess(updateResult) {
//alert(updateResult);
}
function deleteSuccess(deleteResult) {
//alert(deleteResult);
}
function addSuccess(addResult) {
// if addresult is -1, means event was not added
// alert("added key: " + addResult);
if (addResult != -1) {
$('#calendar').fullCalendar('renderEvent',
{
title: $("#addEventName").val(),
start: addStartDate,
end: addEndDate,
id: addResult,
description: $("#addEventDesc").val(),
allDay: globalAllDay
},
true // make the event "stick"
);
$('#calendar').fullCalendar('unselect');
}
}
function UpdateTimeSuccess(updateResult) {
//alert(updateResult);
}
function selectDate(start, end, allDay) {
$('#addDialog').dialog('open');
$("#addEventStartDate").text("" + start.toLocaleString());
$("#addEventEndDate").text("" + end.toLocaleString());
addStartDate = start;
addEndDate = end;
globalAllDay = allDay;
//alert(allDay);
}
function updateEventOnDropResize(event, allDay) {
//alert("allday: " + allDay);
var eventToUpdate = {
id: event.id,
start: event.start
};
if (allDay) {
eventToUpdate.start.setHours(0, 0, 0);
}
if (event.end === null) {
eventToUpdate.end = eventToUpdate.start;
}
else {
eventToUpdate.end = event.end;
if (allDay) {
eventToUpdate.end.setHours(0, 0, 0);
}
}
eventToUpdate.start = eventToUpdate.start.format("DD-MM-YYYY hh:mm A");
eventToUpdate.end = eventToUpdate.end.format("DD-MM-YYYY hh:mm A");
PageMethods.UpdateEventTime(eventToUpdate, UpdateTimeSuccess);
$('#calendar').fullCalendar('refetchEvents');
}
function eventDropped(event, dayDelta, minuteDelta, revertFunc) {
updateEventOnDropResize(event);
}
function eventResized(event, dayDelta, minuteDelta, revertFuncc) {
updateEventOnDropResize(event);
}
function checkForSpecialChars(stringToCheck) {
var pattern = /[^A-Za-z0-9 ]/;
return pattern.test(stringToCheck);
}
$(document).ready(function () {
// update Dialog
$('#updatedialog').dialog({
autoOpen: false,
modal: true,
width: 470,
buttons: {
"update": function () {
//alert(currentUpdateEvent.title);
var eventToUpdate = {
id: currentUpdateEvent.id,
title: $("#eventName").val(),
description: $("#eventDesc").val()
};
if (checkForSpecialChars(eventToUpdate.title) || checkForSpecialChars(eventToUpdate.description)) {
alert("please enter characters: A to Z, a to z, 0 to 9, spaces");
}
else {
PageMethods.UpdateEvent(eventToUpdate, updateSuccess);
$(this).dialog("close");
currentUpdateEvent.title = $("#eventName").val();
currentUpdateEvent.description = $("#eventDesc").val();
$('#calendar').fullCalendar('updateEvent', currentUpdateEvent);
}
},
"delete": function () {
if (confirm("do you really want to delete this event?")) {
PageMethods.deleteEvent($("#eventId").val(), deleteSuccess);
$(this).dialog("close");
$('#calendar').fullCalendar('removeEvents', $("#eventId").val());
}
}
}
});
//add dialog
$('#addDialog').dialog({
autoOpen: false,
width: 470,
buttons: {
"Add": function () {
//alert("sent:" + addStartDate.format("dd-MM-yyyy hh:mm:ss tt") + "==" + addStartDate.toLocaleString());
var eventToAdd = {
title: $("#addEventName").val(),
description: $("#addEventDesc").val(),
start: addStartDate.format("DD-MM-YYYY hh:mm A"),
end: addEndDate.format("DD-MM-YYYY hh:mm A")
};
if (checkForSpecialChars(eventToAdd.title) || checkForSpecialChars(eventToAdd.description)) {
alert("please enter characters: A to Z, a to z, 0 to 9, spaces");
}
else {
//alert("sending " + eventToAdd.title);
PageMethods.addEvent(eventToAdd, addSuccess);
$(this).dialog("close");
}
}
}
});
// page is now ready, initialize the calendar...
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var calendar = $('#calendar').fullCalendar({
// put your options and callbacks here
header:
{
left: 'title',
center: '',
right: 'month,agendaDay,agendaWeek, prev,next'
},
height: 490,
//contentHeight: auto,
titleFormat: 'MMMM D YYYY',
columnFormat: 'ddd D/M',
defaultView: 'agendaWeek',
handleWindowResize: true,
allDaySlot: true,
minTime: '09:00:00',
maxTime: '18:00:00',
slotLabelFormat: 'h(:mm)a',
slotLabelInterval: '01:00:00',
firstDay: 1,
weekends: false,
hiddenDays: [6, 7],
eventClick: updateEvent,
selectable: true,
selectHelper: true,
select: selectDate,
editable: true,
eventDrop: eventDropped,
eventResize: eventResized,
events: {
url: 'JsonResponse.ashx',
color: 'blue',
error: function () {
alert('Error while Getting events!');
}
},
eventRender: function (event, element) {
//alert(event.title);
element.qtip({
content: event.description,
position: { corner: { tooltip: 'bottomLeft', target: 'topRight' } },
style: {
border: {
width: 1,
radius: 3,
color: '#0000ff'
},
padding: 10,
textAlign: 'center',
tip: true, // Give it a speech bubble tip with automatic corner detection
name: 'cream' // Style it according to the preset 'cream' style
}
});
return (event.ranges.filter(function (range) { // test event against all the ranges
return (event.start.isBefore(range.end) &&
event.end.isAfter(range.start));
}).length) > 0;
}
});
});
I may be wrong, but I have a feeling that the issue is that qtip is not able to tell which event is in focus due to the ranges value being passed in. Another thing to note is that if I attempt to resize the event twice it will update the database with the new values but will not actually resize the event on the calendar and the event will not update on the calendar until I refresh the page.
Stack trace from browser:
TypeError: this.eventInstances[0] is undefined
[Learn More]
fullcalendar.min.js:6:26715
s</t.prototype.getEventDef
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:26715
d</t.prototype.isEventInstanceGroupAllowed
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:9:10438
l</e.prototype.isEventInstanceGroupAllowed
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:7:13696
hitOver
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:10:24171
a</t.prototype.trigger
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:15714
l</e.prototype.handleHitOver
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:28967
l</e.prototype.handleDragStart
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:28573
a</t.prototype.startDrag
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:14363
a</t.prototype.handleDistanceSurpassed
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:15289
a</t.prototype.handleMove
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:14610
a</t.prototype.handleMouseMove
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:15474
d
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:2:3854
e
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:16679
dispatch
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:12392
add/r.handle
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:9156
trigger
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:11571
triggerHandler
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:19064
s</e.prototype.trigger
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:16925
u</t.prototype.handleMouseMove
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:20528
d
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:2:3854
dispatch
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:12392
add/r.handle
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:9156
TypeError: t is undefined
[Learn More]
fullcalendar.min.js:8:6813
o</t.prototype.buildNewDateProfile
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:6813
l</t.prototype.mutateSingle
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:7:6026
f</t.prototype.mutateEventsWithId/<
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:11:28483
forEach self-hosted:271:13 f</t.prototype.mutateEventsWithId
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:11:28434
p</e.prototype.reportEventResize
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:7:22052
interactionEnd
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:10:24614
a</t.prototype.trigger
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:15714
a</t.prototype.handleInteractionEnd
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:13682
l</e.prototype.handleInteractionEnd
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:29260
a</t.prototype.endInteraction
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:8:13574
d
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:2:3854
e
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:16679
dispatch
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:12392
add/r.handle
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:9156
trigger
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:11571
triggerHandler
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:19064
s</e.prototype.trigger
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:16925
u</t.prototype.handleMouseUp
http://kmartin41.public.cs.qub.ac.uk/QSIS/js/fullcalendar.min.js:6:20621
d
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:2:3854
dispatch
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:12392
add/r.handle
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js:3:9156
I have based my repeating events off the following answer: https://stackoverflow.com/a/29393128/5659955
Thanks in advance!
As mentioned in my comment there was a bug raised against fullcalendar for resizing events that only have a time for their start and end. github.com/fullcalendar/fullcalendar/issues/3824
To get around this I have taken the calendar start and end range and created a list of all the dates in-between. I then loop over the list and check if the date is a monday(1) and if it matches the dow value in the db (1). I then assign the date to that event and add it to a class object and make a list of the class objects.
Essentially each event has an individual date assigned with the same start and end time. Any time and event is resized it will update the base event in the database and therefore all events are updated.
My solution is in C#.
Table structure:
id event_id startTime endTime startDate endDate dow
2 22 12PM 01PM 3/12/2018 12:00:00 AM 10/15/2018 12:00:00 AM 1
while (reader.Read())
{
int dow;
DateTime startTime;
DateTime endTime;
DateTime newstartdate;
DateTime newenddate;
var datelist = new List<DateTime>();
DateTime tmpdate;
for (int i = 0; i < end.Subtract(start).Days; i++)
{
tmpdate = start.AddDays(i);
datelist.Add(tmpdate);
}
startTime = (DateTime)reader["startTime"];
endTime = (DateTime)reader["endTime"];
dow = (int)reader["dow"];
foreach (DateTime day in datelist.ToList())
{
if((int)day.DayOfWeek == dow)
{
CalendarEvent cevent = new CalendarEvent();
newstartdate = new DateTime(day.Year, day.Month, day.Day, startTime.Hour, startTime.Minute, 0);
newenddate = new DateTime(day.Year, day.Month, day.Day, endTime.Hour, endTime.Minute, 0);
cevent.id = (int)reader["event_id"];
cevent.title = (string)reader["ModuleName"];
cevent.description = (string)reader["Lecturer"];
cevent.start = newstartdate;
cevent.end = newenddate;
DateTime startDate = (DateTime)reader["startDate"];
ceventlist.start = startDate.ToString("yyyy-MM-dd");
DateTime endDate = (DateTime)reader["EndDate"];
ceventlist.end = endDate.ToString("yyyy-MM-dd");
datelist.Remove(day);
cevent.ranges = new List<CalendarEventList>();
cevent.ranges.Add(ceventlist);
events.Add(cevent);
}
}

Fullcalendar, preventing user from selecting multiple day event

In my fullcalendar http://fullcalendar.io/
I want to prevent a user to be able to create an event on multiple days
$('#calendar').fullCalendar({
defaultView: 'agendaWeek',
lang: "fr",
header: false,
timezone: 'local',
minTime: "08:00:00",
columnFormat: 'dddd',
selectHelper: true,
selectable: true,
select: function(start, end, id, allDay) {
var eventData = {
start: start,
end: end,
id: 1,
block: true,
editable: true,
backgroundColor: "#469278"
};
// console.log(moment(eventData.start["_d"]).format("dddd"));
// console.log(moment(eventData.end["_d"]).format("dddd"));
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
// console.log(eventData);
if (moment(eventData.start["_d"]).format("dddd") != moment(eventData.end["_d"]).format("dddd")) {
$('#calendar').fullCalendar('unselect');
};
var day = moment(eventData.start["_d"]).format("dddd");
var start_time = moment(eventData.start["_d"]).format("HH:mm");
var end_time = moment(eventData.end["_d"]).format("HH:mm");
var id = moment(eventData.end["_id"]);
var slot = {
day: day,
start_time: start_time,
end_time: end_time
};
array_dispo.push(slot);
$("#dispo_array").val(JSON.stringify(array_dispo));
$('#calendar').fullCalendar('unselect');
},
});
});
When a user is selecting a start date that is different from the end date of his event I thus tried to use the unselect method from the doc http://fullcalendar.io/docs/selection/unselect_method/ like this :
if (moment(eventData.start["_d"]).format("dddd") != moment(eventData.end["_d"]).format("dddd")) {
$('#calendar').fullCalendar('unselect');
};
But unfortunately this code doesnt automatically deselects the current selection...
You can do a check in your select method and then decide whether you want to render the event or not.
I also use Moment.js to calculate dates and durations, this library is included with FullCalendar (http://fullcalendar.io/docs/utilities/Moment/)
So I played around and came up with this:
select: function (start, end) {
var mEnd = $.fullCalendar.moment(end);
var mStart = $.fullCalendar.moment(start);
if (mEnd.isAfter(mStart, 'day')) {
$('#calendar').fullCalendar('unselect');
} else {
$('#calendar').fullCalendar('renderEvent', {
start: mStart,
end: mEnd,
allDay: false
},
true // stick the event
);
$('#calendar').fullCalendar('unselect');
}
}
Here is the jsfiddle if you want to see it in action: here
You can do it using this way:
eventResize: function(eventResizeInfo) {
console.log('eventResize is called');
var event = eventResizeInfo.event;
if (event.start.getDay() !== event.end.getDay()) {
eventResizeInfo.revert();
}
},
To prevent users from selecting multiple days at a time
selectAllow: function(selectedEvent) {
let startDate = selectedEvent.start;
let endDate = selectedEvent.end;
endDate.setSeconds(endDate.getSeconds() - 1);
if (startDate.getDate() === endDate.getDate()) {
return true;
} else {
return false;
}
}
Simply add the following option to your calendar:
selectAllow: (selectInfo) => { return selectInfo.start.getDay() === selectInfo.end.getDay() },

on refresh full calendar adds duplicate events

On the first load of the page, it shows a single event per day, but on the second load (or refresh of the page) it adds a duplicate event on the same day in the full calendar.
Here is my code:
var CalendarView = Backbone.View.extend({
el : '#calendar-box',
initialize : function() {
// TODO for instance: more instances, Event Bus bindings... only once.
this.calendarModel = new CalendarModel();
$('#calendar-box').hide();
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
this.calendarModel.fetch({
success : function(model, response, options) {
$.unblockUI();
var count=0;
var eventsList=[];
model.attributes.result.forEach(function(){
eventsList.push({
id: model.attributes.result[count].eventId,
title:model.attributes.result[count].title,
start: new Date(model.attributes.result[count].startDate),
end: new Date(model.attributes.result[count].endDate),
attorneyName: model.attributes.result[count].attorneyName,
codeLitOrg: model.attributes.result[count].codeLitOrg,
balance: model.attributes.result[count].balance,
litCode: model.attributes.result[count].litCode
});
count++;
});
if (!_.isEmpty(eventsList)){
$('#calendar').fullCalendar({
editable: true,
events: eventsList,
eventMouseover: function(event, jsEvent, view) {
var info = event.title+'\nBK/LIT: '+event.codeLitOrg+'\nBalance: '+event.balance
+'\nAttorney: '+event.attorneyName+'\nLitCode: '+event.litCode;
$(jsEvent.target).attr('title', info);
},
theme: false,
height:575,
weekMode:'liquid',
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
});
}
},
error : function(model, xhr, options) {
$.unblockUI();
}
});
$.eventBus.on('calendarModalLoaded',function(){
if (!($('.fc-border-separate').html())){
$('#calendar').fullCalendar('today');
}
});
},
render : function() {
// TODO for instance, bindings elements after ready in DOM.
$('#calendar').fullCalendar('today');
return this;
},
events : {
'click a.op-attorney-info' : 'onAttorneyInfo',
'click .go-back-link' : 'goBack'
},
goBack: function(){
$('#calendar-box, .content-box').toggle();
//$('.content-box').toggle();
//$('.go-back-link').hide();
},
onAttorneyInfo : function(ev) {
// TODO for instance, fetch attorney's model
}
});
return CalendarView;
});
I have tried $('#calendar').fullCalendar('removeEvents'), but it is also not working.
Please help me out.

Categories