What would need to be done in order to load .ics files with fullcalendar? I cannot use php or .net unfortunately.
What is an ICS / iCal Feed URL? Most calendar programs allow you to export an iCalendar (. ics or iCal) feed URL. This feed URL contains event data (like times, dates, location, title, description, and time zone) in a standard format. Also each event has a unique identifier or "UID".
There is support for iCalendar as an event source as of V 5.5.0.
You can view the docs here: https://fullcalendar.io/docs/icalendar
Example:
import dayGridPlugin from '@fullcalendar/daygrid'
import iCalendarPlugin from '@fullcalendar/icalendar'
var calendar = new Calendar(calendarEl, {
plugins: [dayGridPlugin, iCalendarPlugin],
events: {
url: 'https://mywebsite/icalendar-feed.ics',
format: 'ics'
}
})
calendar.render()
I manage to do it. Not as hard as I thought. I use ical.js as ics parser. After parsing, I get a json object which contains all the information in the ics. And then traverse it and construct event object according to the definition of FullCalendar Event object.
Update with FullCalendar v4 and reccuring events
As v4 changed the initialization code and the code bellow didn't count with recurring events, here's one that does and works with the v4 version:
$.get(calendarUrl).then(function (data) {
// parse the ics data
var jcalData = ICAL.parse(data.trim());
var comp = new ICAL.Component(jcalData);
var eventComps = comp.getAllSubcomponents("vevent");
// map them to FullCalendar events
var events = $.map(eventComps, function (item) {
if (item.getFirstPropertyValue("class") == "PRIVATE") {
return null;
}
else {
var toreturn = {
"title": item.getFirstPropertyValue("summary"),
"location": item.getFirstPropertyValue("location"),
};
var rrule=item.getFirstPropertyValue("rrule");
if(rrule!= null){ //event recurs
toreturn.rrule={};
if(rrule.freq) toreturn.rrule.freq=rrule.freq;
if(rrule.parts.BYDAY) toreturn.rrule.byweekday=rrule.parts.BYDAY;
if(rrule.until) toreturn.rrule.until=rrule.until.toString();
if(rrule.until) toreturn.rrule.until=rrule.until.toString();
if(rrule.interval) toreturn.rrule.interval=rrule.interval;
var dtstart=item.getFirstPropertyValue("dtstart").toString();
var dtend=item.getFirstPropertyValue("dtend").toString();
toreturn.rrule.dtstart=dtstart;
//count duration ms
var startdate=new Date(dtstart);
var enddate=new Date(dtend);
toreturn.duration = enddate - startdate;
}else{
toreturn.start=item.getFirstPropertyValue("dtstart").toString();
toreturn.end=item.getFirstPropertyValue("dtend").toString();
}
return toreturn;
}
});
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction','dayGrid','rrule' ],
defaultView: 'dayGridWeek',
displayEventEnd: true,
header: {
left: 'prev,next',
center: 'title',
right: 'dayGridDay,dayGridWeek,dayGridMonth'
},
events: events,
eventRender: function (info) {
// console.log(info.event);
// append location
if (info.event.extendedProps.location != null && info.event.extendedProps.location != "") {
info.el.append(info.event.extendedProps.location );
}
}
});
calendar.render();
});
Original answer's code (v3 and lower):
$.get(calendarUrl).then(function (data) {
// parse the ics data
var jcalData = ICAL.parse(data.trim());
var comp = new ICAL.Component(jcalData);
var eventComps = comp.getAllSubcomponents("vevent");
// console.log(JSON.stringify(eventComps));
// map them to FullCalendar events
var events = $.map(eventComps, function (item) {
if (item.getFirstPropertyValue("class") == "PRIVATE") {
return null;
}
else {
return {
"title": item.getFirstPropertyValue("summary") + ";",
"start": item.getFirstPropertyValue("dtstart").toJSDate(),
"end": item.getFirstPropertyValue("dtend").toJSDate(),
"location": item.getFirstPropertyValue("location")
};
}
});
// refresh the control
calendarCtrl.fullCalendar('destroy');
calendarCtrl.fullCalendar({
events: events,
timeFormat: "H:mm",
displayEventEnd: true,
eventRender: function (event, element) {
// console.log(element);
// append location
if (event.location != null && event.location != "") {
element.append("<span>" + event.location + "</span>");
}
},
header: {
left: 'title',
center: '',
right: 'today,month,basicWeek,listDay prev,next'
}
});
});
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