diff --git a/calendar-new.html b/calendar-new.html
new file mode 100644
index 0000000..2fe456f
--- /dev/null
+++ b/calendar-new.html
@@ -0,0 +1,42 @@
+---
+layout: default
+---
+
+
Termine
+
+
+
Coronabedingt sind die Clubräume derzeit geschlossen. Alle Termine finden virtuell statt.
+
+
+
Events
+
+
+ Loading Events, please stand by …
+
+
+
+
+
Regelmäßige Treffen
+
+
+
+
Chaostreff
+
+
Mittwochs, ab ca. 19 Uhr
+ Ein offener Tag für Außenstehende. Jeder, der sich für den CCC oder einen Hackerspace interessiert, ist eingeladen.
+ Um 20:00 Uhr gibt es immer einen Kurzvortrag ‘Petit Foo’ zu ganz unterschiedlichen Themen.
+ Der Chaostreff findet zur Zeit online über Big Blue Button statt:
+ treff.chaospott.de
+
+
+
+
+
+
+
+
Den Kalender gibt es auch per CalDAV. Fehlt etwas? Oder hast du Fragen? Dann schreib uns einfach eine Mail!
+
+
+
+
+
diff --git a/js/calv2.js b/js/calv2.js
new file mode 100644
index 0000000..93b6dea
--- /dev/null
+++ b/js/calv2.js
@@ -0,0 +1,278 @@
+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')
+ //div_description.appendChild(span_summary)
+
+ 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.appendChild(document.createTextNode(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 && !/s(ibyllastra(ss|ß)e )9/i.test(this.location)) {
+ 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 (this.location.match(/tb(a|d)/i)) {
+ span_location.appendChild(document.createTextNode(this.location))
+ } else {
+ 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)
+ }
+
+ div_description.appendChild(span_location)
+ }
+
+ div_cal.appendChild(div_datetime)
+ div_cal.appendChild(div_description)
+
+ if (this.description !== null) {
+ var parts = this.description.split(/\r\n|\r|\n/)
+
+ parts.map(function (i) {
+ var span_description = document.createElement('span')
+ span_description.setAttribute('class', 'cal_description')
+
+ words = i.split(' ')
+
+ words.forEach(function(word) {
+ if (word.match(/(ht|f)tps?\:\/\//i)) {
+ var a = document.createElement('a')
+ a.setAttribute('href', word)
+ a.appendChild(document.createTextNode(word))
+ span_description.appendChild(a)
+ } else {
+ span_description.appendChild(document.createTextNode(word))
+ }
+ span_description.appendChild(document.createTextNode(' '))
+ })
+
+ 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() + 1)
+
+ 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") {
+// console.log(event)
+ 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.textContent = 'No events found.'
+ }
+
+ 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.ru/remote.php/dav/public-calendars/5HM7B0ZOLEYC3QD0?export', processData, requestFailed)