forked from Chaospott/site
		
	Alternative version of the calendar
This commit is contained in:
		
							
								
								
									
										42
									
								
								calendar-new.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								calendar-new.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					layout: default
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					<div class="container">
 | 
				
			||||||
 | 
						<h1>Termine</h1>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<hr />
 | 
				
			||||||
 | 
						<h3>Coronabedingt sind die Clubräume derzeit geschlossen. Alle Termine finden virtuell statt.</h3>
 | 
				
			||||||
 | 
						<hr />
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<h2>Events</h2>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<div id="calendar">
 | 
				
			||||||
 | 
					    		Loading Events, please stand by …
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<hr/>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<h2 >Regelmäßige Treffen</h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<div id="calendar-recurring">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<h3 id="chaostreff">Chaostreff</h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<p><strong>Mittwochs, ab ca. 19 Uhr</strong>
 | 
				
			||||||
 | 
							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:
 | 
				
			||||||
 | 
							<a href="https://treff.chaospott.de">treff.chaospott.de</a></p>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<p >
 | 
				
			||||||
 | 
						</p>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<hr/>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<p >Den Kalender gibt es auch per <a href="webcal://cloud.chaospott.ru/calendar/ical.ics">CalDAV</a>. Fehlt etwas? Oder hast du Fragen? Dann schreib uns einfach eine <a href="mailto:info@chaospott.de">Mail!</a></p>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<script src="js/ical.min.js"></script>
 | 
				
			||||||
 | 
					<script src="js/calv2.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										278
									
								
								js/calv2.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								js/calv2.js
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user