var autolinker = new Autolinker( { urls : { schemeMatches : true, wwwMatches : true, tldMatches : true }, email : true, phone : true, mention : false, hashtag : false, stripPrefix : true, stripTrailingSlash : true, newWindow : true, truncate : { length : 0, location : 'end' }, className : '' } ); var eventList = [] var recurringEventList = [] var cancelledEvents = {} function Event (start, event) { if (!(start instanceof Date)) { start = start.toJSDate() } this.start = start this.event = event this.end = new Date(this.start.getTime() + this.event.duration.toSeconds()*1000) this.summary = event.summary || 'No title' this.description = event.description this.location = event.location || false this.isRecurring = event.isRecurring() this.lasts_several_days = this.start.toDateString() !== this.end.toDateString() } Event.prototype.isCancelled = function () { if (cancelledEvents[this.event.uid] instanceof Array && cancelledEvents[this.event.uid].includes(this.start.getTime())) return true return false } Event.prototype.toHTML = function () { var div_cal = document.createElement('div') if (this.isRecurring) { div_cal.setAttribute('class', 'cal_entry') var div_datetime = document.createElement('div') div_datetime.setAttribute('class', 'cal_datetime') var span_summary = document.createElement('span') span_summary.setAttribute('class', 'cal_summary') span_summary.appendChild(document.createTextNode(this.summary)) div_datetime.appendChild(span_summary) div_cal.appendChild(div_datetime) var div_description = document.createElement('div') div_description.setAttribute('class', 'cal_descriptionbox') var span_description = document.createElement('div') span_description.setAttribute('class', 'cal_description') if (this.description !== null) { var span_description = document.createElement('span') span_description.setAttribute('class', 'cal_description') span_description.innerHTML = autolinker.link( this.description ) } div_description.appendChild(span_description) var span_next = document.createElement('span') span_next.setAttribute('class', 'cal_description') span_next.appendChild(document.createTextNode("Das nächste Treffen findet am " + this.start.toLocaleDateString('de-DE', {year: 'numeric', month: '2-digit', day: '2-digit'}) + " um " + this.start.toLocaleTimeString('de-DE', {hour: '2-digit', minute:'2-digit'}) + " statt." )) div_description.appendChild(span_next) div_cal.appendChild(div_description) } else { div_cal.setAttribute('class', 'cal_entry') var div_datetime = document.createElement('div') div_datetime.setAttribute('class', 'cal_datetime') var span_date = document.createElement('span') span_date.setAttribute('class', 'cal_date') span_date.appendChild(document.createTextNode(this.start.toLocaleDateString('de-DE', {year: 'numeric', month: '2-digit', day: '2-digit'}))) div_datetime.appendChild(span_date) if (this.lasts_several_days) { var span_end_date = document.createElement('span') span_end_date.setAttribute('class', 'cal_date') span_end_date.appendChild(document.createTextNode(' - ' + this.end.toLocaleString('de-DE', {year: 'numeric', month: '2-digit', day: '2-digit'}))) div_datetime.appendChild(span_end_date) } else { var span_day = document.createElement('span') span_day.setAttribute('class', 'cal_day') span_day.appendChild((document.createTextNode(this.start.toLocaleDateString('de-DE', {weekday: 'long'})))) div_datetime.appendChild(span_day) } var span_time = document.createElement('span') span_time.setAttribute('class', 'cal_time') span_time.appendChild(document.createTextNode(this.start.toLocaleTimeString('de-DE', {hour: '2-digit', minute:'2-digit'}))) div_datetime.appendChild(span_time) var span_summary = document.createElement('span') span_summary.setAttribute('class', 'cal_summary') span_summary.appendChild(document.createTextNode(this.summary)) var div_description = document.createElement('div') div_description.setAttribute('class', 'cal_descriptionbox') div_description.appendChild(span_summary) if (this.location !== false) { var span_location = document.createElement('span') span_location.setAttribute('class', 'cal_location') var span_location_icon = document.createElement('i') span_location_icon.setAttribute('class', 'fa fa-map-marker') span_location_icon.setAttribute('aria-hidden', 'true') span_location.appendChild(span_location_icon) if (/s(ibyllastra(ss|ß)e )9/i.test(this.location)) { var a_location_osm = document.createElement('a') a_location_osm.setAttribute('href', 'https://www.openstreetmap.org/search?query=' + encodeURI(this.location)) a_location_osm.appendChild(document.createTextNode(this.location)) span_location.appendChild(a_location_osm) } else { span_location.appendChild(document.createTextNode(this.location)) span_location.innerHTML = autolinker.link( span_location.innerHTML ) } div_description.appendChild(span_location) } div_cal.appendChild(div_datetime) div_cal.appendChild(div_description) if (this.description !== null) { var span_description = document.createElement('span') span_description.setAttribute('class', 'cal_description') span_description.innerHTML = autolinker.link( this.description ) div_description.appendChild(span_description) } // if (this.event.component.getFirstPropertyValue("status") == "CANCELLED") { // div_cal.style.textDecoration = 'line-through' // } } return div_cal } function parseIcalData(data) { var timeRangeStart = new Date() var timeRangeStop = new Date() timeRangeStart.setHours(0, 0, 0) timeRangeStop.setMonth(timeRangeStop.getMonth() + 3) var jcalData = ICAL.parse(data) var vcalendar = new ICAL.Component(jcalData) var events = vcalendar.getAllSubcomponents('vevent') events.map(function (e) { var event = new ICAL.Event(e) if (event.component.getFirstPropertyValue("status") == "CANCELLED") { if (!(cancelledEvents[event.uid] instanceof Array)) { cancelledEvents[event.uid] = [] } cancelledEvents[event.uid].push(event.startDate.toJSDate().getTime()) } else if (event.isRecurring()) { var expand = event.iterator() var next var exList = [] event.component.getAllProperties('exdate').map(function (ex) { exList.push(ex.getFirstValue().toJSDate().getTime()) }) // particularly crappy code, but it works while ((next = expand.next()) && next.toJSDate() < timeRangeStop) { if (!exList.includes(next.toJSDate().getTime()) && timeRangeStart < next.toJSDate() && next.toJSDate() < timeRangeStop) { recurringEventList.push(new Event(next, event)) break } } } else if (eventInTimeRange(event, timeRangeStart, timeRangeStop)) { eventList.push(new Event(event.startDate, event)) } }) } function eventInTimeRange(event, start, stop) { if (start < event.startDate.toJSDate() && event.startDate.toJSDate() < stop || start < event.endDate.toJSDate() && event.endDate.toJSDate() < stop || event.startDate.toJSDate() < start && stop < event.endDate.toJSDate()) return true return false } function orderEvents() { eventList.sort(function (e1, e2) { return e1.start - e2.start }) } function writeEvents() { var cal = document.getElementById('calendar') cal.textContent = '' // TODO: Wenn EventList leer, dann Event-Abschnitt ausblenden if (eventList.length > 0) { eventList.map(function (e) { cal.appendChild(e.toHTML()) }) } else { cal.style.display = "none"; var hevents = document.getElementById('hevents') hevents.style.display = "none"; } var calRecur = document.getElementById('calendar-recurring') calRecur.textContent = '' if (recurringEventList.length > 0) { recurringEventList.map(function (e) { calRecur.appendChild(e.toHTML()) }) } else { calRecur.textContent = 'No events found.' } } function xhrRequest(url, callback, fail) { var xhr = new XMLHttpRequest() xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { callback(xhr.responseText) } else { fail(xhr.status) } } } xhr.open('GET', url) xhr.send() } function processData(data) { parseIcalData(data) orderEvents() writeEvents() } function requestFailed(status) { document.getElementById('calendar').textContent = 'Something has gone wrong. Try reloading the page.' // document.getElementById('calendar-recurring').textContent = 'Something has gone wrong. Try reloading the page.' } xhrRequest('https://cloud.chaospott.de/remote.php/dav/public-calendars/5HM7B0ZOLEYC3QD0?export', processData, requestFailed)