291 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			291 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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)
 | 
