diff --git a/amd/build/RWTHonlineEvents.min.js b/amd/build/RWTHonlineEvents.min.js
index f89c8f8fde77b7950826f7380d8aa49985f3c348..6c9a8a3cac08a12191a3e682d4b914c2d0bf5fea 100644
--- a/amd/build/RWTHonlineEvents.min.js
+++ b/amd/build/RWTHonlineEvents.min.js
@@ -1,2 +1,10 @@
-define ("local_rwth_sd_sync/RWTHonlineEvents",["jquery","core/ajax","core/notification","core/str","core/templates","core_calendar/events","theme_boost/bootstrap/tooltip"],function(a,b,c,d,e,f){var g=function(a){var b=localStorage.getItem("local_rwth_sd_sync/is_rendered_as_rwthonline_event");if(null===b){b=[]}else{b=JSON.parse(b)}return b[a]},h=function(a,b){var c=localStorage.getItem("local_rwth_sd_sync/is_rendered_as_rwthonline_event");if(null===c){c={}}else{c=JSON.parse(c)}c[a]=b;localStorage.setItem("local_rwth_sd_sync/is_rendered_as_rwthonline_event",JSON.stringify(c))},i=function(a,d){var e=g(a);if(e!=void 0){if(!0==e){d()}return}b.call([{methodname:"local_rwth_sd_sync_is_rendered_as_rwthonline_event",args:{id:a}}])[0].done(function(b){if(b){d()}h(a,b)}).fail(c.exception)},j=function(){var f=document.getElementById("page-calendar-view");if(!f){return}var g=new MutationObserver(function callback(f){a.each(f,function(f,g){if(0==g){return!0}a.each(g.addedNodes,function(f,g){var h=a(g).find(".modal-dialog");if(!h.length){return!0}var j=h.find(".modal-body .summary-modal-container");if(!j.length){return!0}var k=j.attr("data-event-id");i(k,function(){var f=a(j).find(".fa-university"),g=f.attr("title"),i=f.parent();i.empty();e.render("local_rwth_sd_sync/rwthonline_event_icon",{title:g}).done(function(a){i.append(a)});var l=h.find(".modal-footer");if(l.find(".rwthonline_event_info_rendered").length){return}d.get_string("rwthonline_event_help","local_rwth_sd_sync").done(function(a){b.call([{methodname:"local_rwth_sd_sync_get_rwthonline_event_url",args:{id:k}}])[0].done(function(b){e.render("local_rwth_sd_sync/rwthonline_event_info_modal",{rwthonlineurl:b,text:a}).done(function(a){l.empty().append(a)})}).fail(c.exception)})})})})});g.observe(f,{childList:!0})},k=function(){a("[data-region=\"event-item\"]").each(function(b,c){var d=a(c).find("a[data-action=\"view-event\"]"),f=d.attr("data-event-id"),g=d.attr("title");d.attr("title",a("<textarea />").html(g).text());i(f,function(){a(c).attr("data-eventtype-rwthonline","1");if(a(c).find(".rwthonline_event_icon_rendered").length){return}var b=a(c).find("i.fa-university, i.fa-group");e.render("local_rwth_sd_sync/rwthonline_event_icon",{}).done(function(a){a=a.replace(" alt=\"\"","").replace(" title=\"\"","");b.replaceWith(a)})})})},l=function(){a(".eventlist .event").each(function(f,g){var h=a(g).attr("data-event-id");i(h,function(){var f=a(g).find("i.fa-university");e.render("local_rwth_sd_sync/rwthonline_event_icon",{}).done(function(a){f.replaceWith(a)});var i=a(g).find(".commands");if(i.find(".rwthonline_event_info_rendered").length){return}d.get_string("rwthonline_event_help","local_rwth_sd_sync").done(function(a){b.call([{methodname:"local_rwth_sd_sync_get_rwthonline_event_url",args:{id:h}}])[0].done(function(b){e.render("local_rwth_sd_sync/rwthonline_event_info_day",{rwthonlineurl:b,text:a}).done(function(a){i.empty().append(a)})}).fail(c.exception)})})})},m=function(){var b=a("[data-eventtype-rwthonline='1']");b.on("dragstart",function(b){b.stopImmediatePropagation();var c=a(b.target);d.get_string("rwthonline_event_tooltip_drag","local_rwth_sd_sync").done(function(a){var b=c.attr("title");c.attr("actual-original-title",b);c.attr("title",a);c.tooltip({container:"body",trigger:"manual",html:!0,template:"<div class=\"tooltip error\" role=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>"});c.tooltip("enable");c.tooltip("show")})});b.on("dragend",function(b){b.stopImmediatePropagation();var c=a(b.target);setTimeout(function(){c.tooltip("hide");c.tooltip("disable");var a=c.attr("actual-original-title");c.attr("title",a)},300)})};return{init:function init(){require(["theme_boost/loader"]);a(document).ready(function(){j();m()});a("body").on(f.viewUpdated,function(){k();l();m()})}}});
-//# sourceMappingURL=RWTHonlineEvents.min.js.map
+/**
+ * RWTHonline events AMD module.
+ *
+ * @module     local_rwth_sd_sync/RWTHonlineEvents
+ * @copyright  2018 Tim Schroeder <t.schroeder@itc.rwth-aachen.de>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("local_rwth_sd_sync/RWTHonlineEvents",["jquery","core/ajax","core/notification","core/str","core/templates","core_calendar/events","theme_boost/bootstrap/tooltip"],(function($,Ajax,Notification,Str,Templates,CalendarEvents){var ifRenderAsRWTHonlineEvent=function(eventid,then){var cachedValue=function(eventid){var cache=localStorage.getItem("local_rwth_sd_sync/is_rendered_as_rwthonline_event");return(cache=null===cache?[]:JSON.parse(cache))[eventid]}(eventid);null==cachedValue?Ajax.call([{methodname:"local_rwth_sd_sync_is_rendered_as_rwthonline_event",args:{id:eventid}}])[0].done((function(renderAsRWTHonlineEvent){renderAsRWTHonlineEvent&&then(),function(eventid,value){var cache=localStorage.getItem("local_rwth_sd_sync/is_rendered_as_rwthonline_event");(cache=null===cache?{}:JSON.parse(cache))[eventid]=value,localStorage.setItem("local_rwth_sd_sync/is_rendered_as_rwthonline_event",JSON.stringify(cache))}(eventid,renderAsRWTHonlineEvent)})).fail(Notification.exception):1==cachedValue&&then()},preventDrag=function(){var rwthonlineEvents=$("[data-eventtype-rwthonline='1']");rwthonlineEvents.on("dragstart",(function(event){event.stopImmediatePropagation();var target=$(event.target);Str.get_string("rwthonline_event_tooltip_drag","local_rwth_sd_sync").done((function(localizedString){var title=target.attr("title");target.attr("actual-original-title",title),target.attr("title",localizedString),target.tooltip({container:"body",trigger:"manual",html:!0,template:'<div class="tooltip error" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'}),target.tooltip("enable"),target.tooltip("show")}))})),rwthonlineEvents.on("dragend",(function(event){event.stopImmediatePropagation();var target=$(event.target);setTimeout((function(){target.tooltip("hide"),target.tooltip("disable");var title=target.attr("actual-original-title");target.attr("title",title)}),300)}))};return{init:function(){require(["theme_boost/loader"]),$(document).ready((function(){!function(){var targetNode=document.getElementById("page-calendar-view");if(targetNode){var observer=new MutationObserver((function(mutationsList){mutationsList.forEach((function(mutation){if(0==mutation)return!0;mutation.addedNodes.forEach((function(node){if("DIV"==node.nodeName&&""==node.innerHTML&&0==node.childNodes.length)return observer.observe(node,{childList:!0}),!0;var dialog=node.classList.contains("summary-modal-container")?document.querySelector("#page-calendar-view .modal-dialog"):node.querySelector(".modal-dialog"),summaryContainer=node.classList.contains("summary-modal-container")?node:node.querySelector(".modal-body .summary-modal-container");if(!dialog&&!summaryContainer)return!0;if(dialog&&!summaryContainer)return observer.observe(node.querySelector(".modal-body"),{childList:!0}),!0;var eventid=summaryContainer.getAttribute("data-event-id");ifRenderAsRWTHonlineEvent(eventid,(function(){var footer=dialog.querySelector(".modal-footer");if(footer.querySelector(".rwthonline_event_info_rendered"))return!0;Str.get_string("rwthonline_event_help","local_rwth_sd_sync").done((function(localizedString){Ajax.call([{methodname:"local_rwth_sd_sync_get_rwthonline_event_url",args:{id:eventid},done:function(rwthonlineurl){Templates.render("local_rwth_sd_sync/rwthonline_event_info_modal",{rwthonlineurl:rwthonlineurl,text:localizedString}).done((function(rwthonlineInfo){footer.innerHTML=rwthonlineInfo,footer.classList.remove("hidden")}))},fail:function(ex){Notification.exception(ex)}}])}))}))}))}))}));observer.observe(targetNode,{childList:!0})}}(),preventDrag()})),$("body").on(CalendarEvents.viewUpdated,(function(){$('[data-region="event-item"]').each((function(evtIdx,event){var link=$(event).find('a[data-action="view-event"]'),title=link.attr("title");link.attr("title",$("<textarea />").html(title).text())})),$(".eventlist .event").each((function(evtIdx,event){var eventid=$(event).attr("data-event-id");ifRenderAsRWTHonlineEvent(eventid,(function(){var commands=$(event).find(".commands");commands.find(".rwthonline_event_info_rendered").length||Str.get_string("rwthonline_event_help","local_rwth_sd_sync").done((function(localizedString){Ajax.call([{methodname:"local_rwth_sd_sync_get_rwthonline_event_url",args:{id:eventid}}])[0].done((function(rwthonlineurl){Templates.render("local_rwth_sd_sync/rwthonline_event_info_day",{rwthonlineurl:rwthonlineurl,text:localizedString}).done((function(rwthonlineInfo){commands.empty().append(rwthonlineInfo)}))})).fail(Notification.exception)}))}))})),preventDrag()}))}}}));
+
+//# sourceMappingURL=RWTHonlineEvents.min.js.map
\ No newline at end of file
diff --git a/amd/build/RWTHonlineEvents.min.js.map b/amd/build/RWTHonlineEvents.min.js.map
index 27d6f985eda4aa1306520f729de9f81cb934ad7c..61d26ce586b64a7b7ce2185125208d05dcfc19c0 100644
--- a/amd/build/RWTHonlineEvents.min.js.map
+++ b/amd/build/RWTHonlineEvents.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/RWTHonlineEvents.js"],"names":["define","$","Ajax","Notification","Str","Templates","CalendarEvents","cacheGetRenderAsRWTHonlineEvent","eventid","cache","localStorage","getItem","JSON","parse","cacheSetRenderAsRWTHonlineEvent","value","setItem","stringify","ifRenderAsRWTHonlineEvent","then","cachedValue","call","methodname","args","id","done","renderAsRWTHonlineEvent","fail","exception","fixModal","targetNode","document","getElementById","observer","MutationObserver","callback","mutationsList","each","mutIdx","mutation","addedNodes","nodeIdx","node","dialog","find","length","summaryContainer","attr","eventicon","eventicontitle","eventiconcol","parent","empty","render","icon","append","footer","get_string","localizedString","rwthonlineurl","text","rwthonlineInfo","observe","childList","fixMonthView","evtIdx","event","link","title","html","replace","replaceWith","fixDayView","commands","preventDrag","rwthonlineEvents","on","stopImmediatePropagation","target","tooltip","container","trigger","template","setTimeout","init","require","ready","viewUpdated"],"mappings":"AAuBAA,OAAM,uCAAC,CACH,QADG,CAEH,WAFG,CAGH,mBAHG,CAIH,UAJG,CAKH,gBALG,CAMH,sBANG,CAOH,+BAPG,CAAD,CAQH,SACCC,CADD,CAECC,CAFD,CAGCC,CAHD,CAICC,CAJD,CAKCC,CALD,CAMCC,CAND,CAOD,IAEMC,CAAAA,CAA+B,CAAG,SAASC,CAAT,CAAkB,CACpD,GAAIC,CAAAA,CAAK,CAAGC,YAAY,CAACC,OAAb,CAAqB,oDAArB,CAAZ,CACA,GAAc,IAAV,GAAAF,CAAJ,CAAoB,CAChBA,CAAK,CAAG,EACX,CAFD,IAEO,CACHA,CAAK,CAAGG,IAAI,CAACC,KAAL,CAAWJ,CAAX,CACX,CACD,MAAOA,CAAAA,CAAK,CAACD,CAAD,CACf,CAVH,CAYMM,CAA+B,CAAG,SAASN,CAAT,CAAkBO,CAAlB,CAAyB,CAC3D,GAAIN,CAAAA,CAAK,CAAGC,YAAY,CAACC,OAAb,CAAqB,oDAArB,CAAZ,CACA,GAAc,IAAV,GAAAF,CAAJ,CAAoB,CAChBA,CAAK,CAAG,EACX,CAFD,IAEO,CACHA,CAAK,CAAGG,IAAI,CAACC,KAAL,CAAWJ,CAAX,CACX,CACDA,CAAK,CAACD,CAAD,CAAL,CAAiBO,CAAjB,CACAL,YAAY,CAACM,OAAb,CAAqB,oDAArB,CAA2EJ,IAAI,CAACK,SAAL,CAAeR,CAAf,CAA3E,CACH,CArBH,CAuBMS,CAAyB,CAAG,SAASV,CAAT,CAAkBW,CAAlB,CAAwB,CACpD,GAAIC,CAAAA,CAAW,CAAGb,CAA+B,CAACC,CAAD,CAAjD,CACA,GAAIY,CAAW,QAAf,CAA8B,CAE1B,GAAI,IAAAA,CAAJ,CAAyB,CACrBD,CAAI,EACP,CACD,MACH,CAGDjB,CAAI,CAACmB,IAAL,CAAU,CACN,CAACC,UAAU,CAAE,oDAAb,CAAmEC,IAAI,CAAE,CACrEC,EAAE,CAAEhB,CADiE,CAAzE,CADM,CAAV,EAIG,CAJH,EAIMiB,IAJN,CAIW,SAASC,CAAT,CAAkC,CACzC,GAAIA,CAAJ,CAA6B,CACzBP,CAAI,EACP,CACDL,CAA+B,CAACN,CAAD,CAAUkB,CAAV,CAClC,CATD,EASGC,IATH,CASQxB,CAAY,CAACyB,SATrB,CAUH,CA5CH,CA+CMC,CAAQ,CAAG,UAAW,CACtB,GAAIC,CAAAA,CAAU,CAAGC,QAAQ,CAACC,cAAT,CAAwB,oBAAxB,CAAjB,CACA,GAAI,CAACF,CAAL,CAAiB,CACb,MACH,CAJqB,GA0DlBG,CAAAA,CAAQ,CAAG,GAAIC,CAAAA,gBAAJ,CApDA,QAAXC,CAAAA,QAAW,CAASC,CAAT,CAAwB,CACnCnC,CAAC,CAACoC,IAAF,CAAOD,CAAP,CAAsB,SAASE,CAAT,CAAiBC,CAAjB,CAA2B,CAC7C,GAAgB,CAAZ,EAAAA,CAAJ,CAAmB,CACf,QACH,CACDtC,CAAC,CAACoC,IAAF,CAAOE,CAAQ,CAACC,UAAhB,CAA4B,SAASC,CAAT,CAAkBC,CAAlB,CAAwB,CAChD,GAAIC,CAAAA,CAAM,CAAG1C,CAAC,CAACyC,CAAD,CAAD,CAAQE,IAAR,CAAa,eAAb,CAAb,CACA,GAAI,CAACD,CAAM,CAACE,MAAZ,CAAoB,CAEhB,QACH,CAED,GAAIC,CAAAA,CAAgB,CAAGH,CAAM,CAACC,IAAP,CAAY,sCAAZ,CAAvB,CACA,GAAI,CAACE,CAAgB,CAACD,MAAtB,CAA8B,CAE1B,QACH,CAED,GAAIrC,CAAAA,CAAO,CAAGsC,CAAgB,CAACC,IAAjB,CAAsB,eAAtB,CAAd,CACA7B,CAAyB,CAACV,CAAD,CAAU,UAAW,IAEtCwC,CAAAA,CAAS,CAAG/C,CAAC,CAAC6C,CAAD,CAAD,CAAoBF,IAApB,CAAyB,gBAAzB,CAF0B,CAGtCK,CAAc,CAAGD,CAAS,CAACD,IAAV,CAAe,OAAf,CAHqB,CAItCG,CAAY,CAAGF,CAAS,CAACG,MAAV,EAJuB,CAK1CD,CAAY,CAACE,KAAb,GACA/C,CAAS,CAACgD,MAAV,CAAiB,0CAAjB,CACQ,CAAC,MAASJ,CAAV,CADR,EACmCxB,IADnC,CACwC,SAAS6B,CAAT,CAAe,CACnDJ,CAAY,CAACK,MAAb,CAAoBD,CAApB,CACH,CAHD,EAMA,GAAIE,CAAAA,CAAM,CAAGb,CAAM,CAACC,IAAP,CAAY,eAAZ,CAAb,CACA,GAAIY,CAAM,CAACZ,IAAP,CAAY,iCAAZ,EAA+CC,MAAnD,CAA2D,CAEvD,MACH,CACDzC,CAAG,CAACqD,UAAJ,CAAe,uBAAf,CAAwC,oBAAxC,EAA8DhC,IAA9D,CAAmE,SAASiC,CAAT,CAA0B,CACzFxD,CAAI,CAACmB,IAAL,CAAU,CACN,CAACC,UAAU,CAAE,6CAAb,CAA4DC,IAAI,CAAE,CAC9DC,EAAE,CAAEhB,CAD0D,CAAlE,CADM,CAAV,EAIG,CAJH,EAIMiB,IAJN,CAIW,SAASkC,CAAT,CAAwB,CAC/BtD,CAAS,CAACgD,MAAV,CAAiB,gDAAjB,CACQ,CAACM,aAAa,CAAEA,CAAhB,CAA+BC,IAAI,CAAEF,CAArC,CADR,EAC+DjC,IAD/D,CACoE,SAASoC,CAAT,CAAyB,CACzFL,CAAM,CAACJ,KAAP,GAAeG,MAAf,CAAsBM,CAAtB,CACH,CAHD,CAIH,CATD,EASGlC,IATH,CASQxB,CAAY,CAACyB,SATrB,CAUH,CAXD,CAYH,CA7BwB,CA8B5B,CA5CD,CA6CH,CAjDD,CAkDH,CACc,CA1DO,CA2DtBK,CAAQ,CAAC6B,OAAT,CAAiBhC,CAAjB,CAtDa,CAAEiC,SAAS,GAAX,CAsDb,CACH,CA3GH,CA8GMC,CAAY,CAAG,UAAW,CAC1B/D,CAAC,CAAC,8BAAD,CAAD,CAAgCoC,IAAhC,CAAqC,SAAS4B,CAAT,CAAiBC,CAAjB,CAAwB,IACrDC,CAAAA,CAAI,CAAGlE,CAAC,CAACiE,CAAD,CAAD,CAAStB,IAAT,CAAc,+BAAd,CAD8C,CAErDpC,CAAO,CAAG2D,CAAI,CAACpB,IAAL,CAAU,eAAV,CAF2C,CAGrDqB,CAAK,CAAGD,CAAI,CAACpB,IAAL,CAAU,OAAV,CAH6C,CAIzDoB,CAAI,CAACpB,IAAL,CAAU,OAAV,CAAmB9C,CAAC,CAAC,cAAD,CAAD,CAAkBoE,IAAlB,CAAuBD,CAAvB,EAA8BR,IAA9B,EAAnB,EAEA1C,CAAyB,CAACV,CAAD,CAAU,UAAW,CAE1CP,CAAC,CAACiE,CAAD,CAAD,CAASnB,IAAT,CAAc,2BAAd,CAA2C,GAA3C,EAGA,GAAI9C,CAAC,CAACiE,CAAD,CAAD,CAAStB,IAAT,CAAc,iCAAd,EAAiDC,MAArD,CAA6D,CAEzD,MACH,CACD,GAAIG,CAAAA,CAAS,CAAG/C,CAAC,CAACiE,CAAD,CAAD,CAAStB,IAAT,CAAc,6BAAd,CAAhB,CACAvC,CAAS,CAACgD,MAAV,CAAiB,0CAAjB,CAA6D,EAA7D,EAAiE5B,IAAjE,CAAsE,SAAS6B,CAAT,CAAe,CACjFA,CAAI,CAAGA,CAAI,CAACgB,OAAL,CAAa,WAAb,CAAwB,EAAxB,EAA4BA,OAA5B,CAAoC,aAApC,CAAiD,EAAjD,CAAP,CACAtB,CAAS,CAACuB,WAAV,CAAsBjB,CAAtB,CACH,CAHD,CAIH,CAdwB,CAe5B,CArBD,CAsBH,CArIH,CAwIMkB,CAAU,CAAG,UAAW,CACxBvE,CAAC,CAAC,mBAAD,CAAD,CAAuBoC,IAAvB,CAA4B,SAAS4B,CAAT,CAAiBC,CAAjB,CAAwB,CAChD,GAAI1D,CAAAA,CAAO,CAAGP,CAAC,CAACiE,CAAD,CAAD,CAASnB,IAAT,CAAc,eAAd,CAAd,CAGA7B,CAAyB,CAACV,CAAD,CAAU,UAAW,CAE1C,GAAIwC,CAAAA,CAAS,CAAG/C,CAAC,CAACiE,CAAD,CAAD,CAAStB,IAAT,CAAc,iBAAd,CAAhB,CACAvC,CAAS,CAACgD,MAAV,CAAiB,0CAAjB,CAA6D,EAA7D,EAAiE5B,IAAjE,CAAsE,SAAS6B,CAAT,CAAe,CACjFN,CAAS,CAACuB,WAAV,CAAsBjB,CAAtB,CACH,CAFD,EAKA,GAAImB,CAAAA,CAAQ,CAAGxE,CAAC,CAACiE,CAAD,CAAD,CAAStB,IAAT,CAAc,WAAd,CAAf,CACA,GAAI6B,CAAQ,CAAC7B,IAAT,CAAc,iCAAd,EAAiDC,MAArD,CAA6D,CAEzD,MACH,CACDzC,CAAG,CAACqD,UAAJ,CAAe,uBAAf,CAAwC,oBAAxC,EAA8DhC,IAA9D,CAAmE,SAASiC,CAAT,CAA0B,CACzFxD,CAAI,CAACmB,IAAL,CAAU,CACN,CAACC,UAAU,CAAE,6CAAb,CAA4DC,IAAI,CAAE,CAC9DC,EAAE,CAAEhB,CAD0D,CAAlE,CADM,CAAV,EAIG,CAJH,EAIMiB,IAJN,CAIW,SAASkC,CAAT,CAAwB,CAC/BtD,CAAS,CAACgD,MAAV,CAAiB,8CAAjB,CACQ,CAACM,aAAa,CAAEA,CAAhB,CAA+BC,IAAI,CAAEF,CAArC,CADR,EAC+DjC,IAD/D,CACoE,SAASoC,CAAT,CAAyB,CACzFY,CAAQ,CAACrB,KAAT,GAAiBG,MAAjB,CAAwBM,CAAxB,CACH,CAHD,CAIH,CATD,EASGlC,IATH,CASQxB,CAAY,CAACyB,SATrB,CAUH,CAXD,CAYH,CAzBwB,CA0B5B,CA9BD,CA+BH,CAxKH,CA2KM8C,CAAW,CAAG,UAAW,CACzB,GAAIC,CAAAA,CAAgB,CAAG1E,CAAC,CAAC,iCAAD,CAAxB,CACA0E,CAAgB,CAACC,EAAjB,CAAoB,WAApB,CAAiC,SAASV,CAAT,CAAgB,CAC7CA,CAAK,CAACW,wBAAN,GACA,GAAIC,CAAAA,CAAM,CAAG7E,CAAC,CAACiE,CAAK,CAACY,MAAP,CAAd,CAEA1E,CAAG,CAACqD,UAAJ,CAAe,+BAAf,CAAgD,oBAAhD,EAAsEhC,IAAtE,CAA2E,SAASiC,CAAT,CAA0B,CAGjG,GAAIU,CAAAA,CAAK,CAAGU,CAAM,CAAC/B,IAAP,CAAY,OAAZ,CAAZ,CACA+B,CAAM,CAAC/B,IAAP,CAAY,uBAAZ,CAAqCqB,CAArC,EAGAU,CAAM,CAAC/B,IAAP,CAAY,OAAZ,CAAqBW,CAArB,EACAoB,CAAM,CAACC,OAAP,CAAe,CACXC,SAAS,CAAE,MADA,CAEXC,OAAO,CAAE,QAFE,CAGXZ,IAAI,GAHO,CAIXa,QAAQ,6HAJG,CAAf,EAOAJ,CAAM,CAACC,OAAP,CAAe,QAAf,EACAD,CAAM,CAACC,OAAP,CAAe,MAAf,CACH,CAjBD,CAmBH,CAvBD,EAwBAJ,CAAgB,CAACC,EAAjB,CAAoB,SAApB,CAA+B,SAASV,CAAT,CAAgB,CAC3CA,CAAK,CAACW,wBAAN,GACA,GAAIC,CAAAA,CAAM,CAAG7E,CAAC,CAACiE,CAAK,CAACY,MAAP,CAAd,CAGAK,UAAU,CAAC,UAAW,CAElBL,CAAM,CAACC,OAAP,CAAe,MAAf,EACAD,CAAM,CAACC,OAAP,CAAe,SAAf,EAGA,GAAIX,CAAAA,CAAK,CAAGU,CAAM,CAAC/B,IAAP,CAAY,uBAAZ,CAAZ,CACA+B,CAAM,CAAC/B,IAAP,CAAY,OAAZ,CAAqBqB,CAArB,CACH,CARS,CAQP,GARO,CASb,CAdD,CAeH,CApNH,CAsNE,MAAO,CACHgB,IAAI,CAAE,eAAW,CAGbC,OAAO,CAAC,CAAC,oBAAD,CAAD,CAAP,CAEApF,CAAC,CAAC8B,QAAD,CAAD,CAAYuD,KAAZ,CAAkB,UAAW,CACzBzD,CAAQ,GACR6C,CAAW,EACd,CAHD,EAIAzE,CAAC,CAAC,MAAD,CAAD,CAAU2E,EAAV,CAAatE,CAAc,CAACiF,WAA5B,CAAyC,UAAW,CAChDvB,CAAY,GACZQ,CAAU,GACVE,CAAW,EACd,CAJD,CAKH,CAfE,CAiBV,CAtPK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * RWTHonline events AMD module.\n *\n * @module     local_rwth_sd_sync/RWTHonlineEvents\n * @copyright  2018 Tim Schroeder <t.schroeder@itc.rwth-aachen.de>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine([\n    'jquery',\n    'core/ajax',\n    'core/notification',\n    'core/str',\n    'core/templates',\n    'core_calendar/events',\n    'theme_boost/bootstrap/tooltip'\n], function(\n    $,\n    Ajax,\n    Notification,\n    Str,\n    Templates,\n    CalendarEvents\n) {\n\n    var cacheGetRenderAsRWTHonlineEvent = function(eventid) {\n        var cache = localStorage.getItem('local_rwth_sd_sync/is_rendered_as_rwthonline_event');\n        if (cache === null) {\n            cache = [];\n        } else {\n            cache = JSON.parse(cache);\n        }\n        return cache[eventid];\n    };\n\n    var cacheSetRenderAsRWTHonlineEvent = function(eventid, value) {\n        var cache = localStorage.getItem('local_rwth_sd_sync/is_rendered_as_rwthonline_event');\n        if (cache === null) {\n            cache = {};\n        } else {\n            cache = JSON.parse(cache);\n        }\n        cache[eventid] = value;\n        localStorage.setItem('local_rwth_sd_sync/is_rendered_as_rwthonline_event', JSON.stringify(cache));\n    };\n\n    var ifRenderAsRWTHonlineEvent = function(eventid, then) {\n        var cachedValue = cacheGetRenderAsRWTHonlineEvent(eventid);\n        if (cachedValue != undefined) {\n            // We already queried this event.\n            if (cachedValue == true) {\n                then();\n            }\n            return;\n        }\n\n        // Event has not been queried.\n        Ajax.call([\n            {methodname: 'local_rwth_sd_sync_is_rendered_as_rwthonline_event', args: {\n                id: eventid\n            }}\n        ])[0].done(function(renderAsRWTHonlineEvent) {\n            if (renderAsRWTHonlineEvent) {\n                then();\n            }\n            cacheSetRenderAsRWTHonlineEvent(eventid, renderAsRWTHonlineEvent);\n        }).fail(Notification.exception);\n    };\n\n    // Remove edit/delete buttons from modals in month view.\n    var fixModal = function() {\n        var targetNode = document.getElementById('page-calendar-view');\n        if (!targetNode) {\n            return;\n        }\n        var config = { childList: true };\n        var callback = function(mutationsList) {\n            $.each(mutationsList, function(mutIdx, mutation) {\n                if (mutation == 0) {\n                    return true;\n                }\n                $.each(mutation.addedNodes, function(nodeIdx, node) {\n                    var dialog = $(node).find('.modal-dialog');\n                    if (!dialog.length) {\n                        // Not a modal dialog.\n                        return true;\n                    }\n\n                    var summaryContainer = dialog.find('.modal-body .summary-modal-container');\n                    if (!summaryContainer.length) {\n                        // Not the modal content we are looking for.\n                        return true;\n                    }\n\n                    var eventid = summaryContainer.attr('data-event-id');\n                    ifRenderAsRWTHonlineEvent(eventid, function() {\n                        // Replace icon (the icon in the first <div> of the last row).\n                        var eventicon = $(summaryContainer).find('.fa-university');\n                        var eventicontitle = eventicon.attr(\"title\");\n                        var eventiconcol = eventicon.parent();\n                        eventiconcol.empty();\n                        Templates.render('local_rwth_sd_sync/rwthonline_event_icon',\n                                {'title': eventicontitle}).done(function(icon) {\n                            eventiconcol.append(icon);\n                        });\n\n                        // Remove edit/delete buttons.\n                        var footer = dialog.find('.modal-footer');\n                        if (footer.find(\".rwthonline_event_info_rendered\").length) {\n                            // Edit/delete buttons already removed.\n                            return;\n                        }\n                        Str.get_string('rwthonline_event_help', 'local_rwth_sd_sync').done(function(localizedString) {\n                            Ajax.call([\n                                {methodname: 'local_rwth_sd_sync_get_rwthonline_event_url', args: {\n                                    id: eventid\n                                }}\n                            ])[0].done(function(rwthonlineurl) {\n                                Templates.render('local_rwth_sd_sync/rwthonline_event_info_modal',\n                                        {rwthonlineurl: rwthonlineurl, text: localizedString}).done(function(rwthonlineInfo) {\n                                    footer.empty().append(rwthonlineInfo);\n                                });\n                            }).fail(Notification.exception);\n                        });\n                    });\n                });\n            });\n        };\n        var observer = new MutationObserver(callback);\n        observer.observe(targetNode, config);\n    };\n\n    // Mark RWTHonline events as such.\n    var fixMonthView = function() {\n        $('[data-region=\"event-item\"]').each(function(evtIdx, event) {\n            var link = $(event).find('a[data-action=\"view-event\"]');\n            var eventid = link.attr('data-event-id');\n            var title = link.attr('title');\n            link.attr('title', $('<textarea />').html(title).text()); // JS equivalent of PHP html_entity_decode\n\n            ifRenderAsRWTHonlineEvent(eventid, function() {\n                // Mark as a rwthonline event, e.g. for drag-and-drop handling.\n                $(event).attr('data-eventtype-rwthonline', '1');\n\n                // Replace icon.\n                if ($(event).find(\".rwthonline_event_icon_rendered\").length) {\n                    // Icon already replaced.\n                    return;\n                }\n                var eventicon = $(event).find('i.fa-university, i.fa-group');\n                Templates.render('local_rwth_sd_sync/rwthonline_event_icon', {}).done(function(icon) {\n                    icon = icon.replace(' alt=\"\"', '').replace(' title=\"\"', '');\n                    eventicon.replaceWith(icon);\n                });\n            });\n        });\n    };\n\n    // Mark RWTHonline events as such and remove edit/delete buttons from day view.\n    var fixDayView = function() {\n        $(\".eventlist .event\").each(function(evtIdx, event) {\n            var eventid = $(event).attr('data-event-id');\n\n            // Check if the event shoud be rendered as a RWTHonline event.\n            ifRenderAsRWTHonlineEvent(eventid, function() {\n                // Replace icon.\n                var eventicon = $(event).find('i.fa-university');\n                Templates.render('local_rwth_sd_sync/rwthonline_event_icon', {}).done(function(icon) {\n                    eventicon.replaceWith(icon);\n                });\n\n                // Replace command buttons with text.\n                var commands = $(event).find('.commands');\n                if (commands.find(\".rwthonline_event_info_rendered\").length) {\n                    // Command buttons already replaced.\n                    return;\n                }\n                Str.get_string('rwthonline_event_help', 'local_rwth_sd_sync').done(function(localizedString) {\n                    Ajax.call([\n                        {methodname: 'local_rwth_sd_sync_get_rwthonline_event_url', args: {\n                            id: eventid\n                        }}\n                    ])[0].done(function(rwthonlineurl) {\n                        Templates.render('local_rwth_sd_sync/rwthonline_event_info_day',\n                                {rwthonlineurl: rwthonlineurl, text: localizedString}).done(function(rwthonlineInfo) {\n                            commands.empty().append(rwthonlineInfo);\n                        });\n                    }).fail(Notification.exception);\n                });\n            });\n        });\n    };\n\n    // Prevent drag-and-drop.\n    var preventDrag = function() {\n        var rwthonlineEvents = $(\"[data-eventtype-rwthonline='1']\");\n        rwthonlineEvents.on(\"dragstart\", function(event) {\n            event.stopImmediatePropagation();\n            var target = $(event.target);\n\n            Str.get_string('rwthonline_event_tooltip_drag', 'local_rwth_sd_sync').done(function(localizedString) {\n\n                // Store title in another attribute.\n                var title = target.attr('title');\n                target.attr('actual-original-title', title);\n\n                // Show tooltip.\n                target.attr('title', localizedString);\n                target.tooltip({\n                    container: \"body\",\n                    trigger: \"manual\",\n                    html: true,\n                    template: '<div class=\"tooltip error\" role=\"tooltip\">'\n                        + '<div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n                });\n                target.tooltip('enable');\n                target.tooltip('show');\n            });\n\n        });\n        rwthonlineEvents.on(\"dragend\", function(event) {\n            event.stopImmediatePropagation();\n            var target = $(event.target);\n\n            // Delay hiding the tootip slightly.\n            setTimeout(function() {\n                // Hide tooltip.\n                target.tooltip('hide');\n                target.tooltip('disable');\n\n                // Restore title.\n                var title = target.attr('actual-original-title');\n                target.attr('title', title);\n            }, 300);\n        });\n    };\n\n    return {\n        init: function() {\n\n            // Load Boost tooltips.\n            require(['theme_boost/loader']);\n\n            $(document).ready(function() {\n                fixModal();\n                preventDrag();\n            });\n            $('body').on(CalendarEvents.viewUpdated, function() {\n                fixMonthView();\n                fixDayView();\n                preventDrag();\n            });\n        }\n    };\n});"],"file":"RWTHonlineEvents.min.js"}
\ No newline at end of file
+{"version":3,"file":"RWTHonlineEvents.min.js","sources":["../src/RWTHonlineEvents.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * RWTHonline events AMD module.\n *\n * @module     local_rwth_sd_sync/RWTHonlineEvents\n * @copyright  2018 Tim Schroeder <t.schroeder@itc.rwth-aachen.de>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine([\n    'jquery',\n    'core/ajax',\n    'core/notification',\n    'core/str',\n    'core/templates',\n    'core_calendar/events',\n    'theme_boost/bootstrap/tooltip'\n], function(\n    $,\n    Ajax,\n    Notification,\n    Str,\n    Templates,\n    CalendarEvents\n) {\n\n    var cacheGetRenderAsRWTHonlineEvent = function(eventid) {\n        var cache = localStorage.getItem('local_rwth_sd_sync/is_rendered_as_rwthonline_event');\n        if (cache === null) {\n            cache = [];\n        } else {\n            cache = JSON.parse(cache);\n        }\n        return cache[eventid];\n    };\n\n    var cacheSetRenderAsRWTHonlineEvent = function(eventid, value) {\n        var cache = localStorage.getItem('local_rwth_sd_sync/is_rendered_as_rwthonline_event');\n        if (cache === null) {\n            cache = {};\n        } else {\n            cache = JSON.parse(cache);\n        }\n        cache[eventid] = value;\n        localStorage.setItem('local_rwth_sd_sync/is_rendered_as_rwthonline_event', JSON.stringify(cache));\n    };\n\n    var ifRenderAsRWTHonlineEvent = function(eventid, then) {\n        var cachedValue = cacheGetRenderAsRWTHonlineEvent(eventid);\n        if (cachedValue != undefined) {\n            // We already queried this event.\n            if (cachedValue == true) {\n                then();\n            }\n            return;\n        }\n\n        // Event has not been queried.\n        Ajax.call([\n            {methodname: 'local_rwth_sd_sync_is_rendered_as_rwthonline_event', args: {\n                id: eventid\n            }}\n        ])[0].done(function(renderAsRWTHonlineEvent) {\n            if (renderAsRWTHonlineEvent) {\n                then();\n            }\n            cacheSetRenderAsRWTHonlineEvent(eventid, renderAsRWTHonlineEvent);\n        }).fail(Notification.exception);\n    };\n\n    // Remove edit/delete buttons from modals in month view.\n    var fixModal = function() {\n        var targetNode = document.getElementById('page-calendar-view');\n        if (!targetNode) {\n            return;\n        }\n        var config = { childList: true };\n        var callback = function(mutationsList) {\n            mutationsList.forEach(function(mutation) {\n                if (mutation == 0) {\n                    return true;\n                }\n                mutation.addedNodes.forEach(function(node) {\n                    if (node.nodeName == \"DIV\" && node.innerHTML == \"\" && node.childNodes.length == 0) {\n                        observer.observe(node, {childList: true});\n                        return true;\n                    }\n                    var dialog = node.classList.contains('summary-modal-container') ?\n                        document.querySelector('#page-calendar-view .modal-dialog') : node.querySelector('.modal-dialog');\n                    var summaryContainer = node.classList.contains('summary-modal-container') ?\n                        node : node.querySelector('.modal-body .summary-modal-container');\n\n                    if (!dialog && !summaryContainer) {\n                        // Not a modal dialog.\n                        return true;\n                    }\n\n                    if (dialog && !summaryContainer) {\n                        // Modal body is loaded but content still loading, await insertion of content block\n                        observer.observe(node.querySelector('.modal-body'), {childList: true});\n                        return true;\n                    }\n\n                    var eventid = summaryContainer.getAttribute('data-event-id');\n                    ifRenderAsRWTHonlineEvent(eventid, function() {\n\n                        // Do not render twice\n                        var footer = dialog.querySelector('.modal-footer');\n                        if (footer.querySelector(\".rwthonline_event_info_rendered\")) {\n                            // Already rendered\n                            return true;\n                        }\n\n                        Str.get_string('rwthonline_event_help', 'local_rwth_sd_sync').done(function(localizedString) {\n                            Ajax.call([{\n                                methodname: 'local_rwth_sd_sync_get_rwthonline_event_url',\n                                args: {\n                                    id: eventid\n                                },\n                                done: function(rwthonlineurl) {\n                                    Templates.render('local_rwth_sd_sync/rwthonline_event_info_modal',\n                                        {rwthonlineurl: rwthonlineurl, text: localizedString})\n                                    .done(function(rwthonlineInfo) {\n                                        footer.innerHTML = rwthonlineInfo;\n                                        footer.classList.remove(\"hidden\");\n                                    });\n                                },\n                                fail: function(ex) {\n                                    Notification.exception(ex);\n                                },\n                            }]);\n                        });\n                    });\n                });\n            });\n        };\n        var observer = new MutationObserver(callback);\n        observer.observe(targetNode, config);\n    };\n\n    // Mark RWTHonline events as such.\n    var fixMonthView = function() {\n        $('[data-region=\"event-item\"]').each(function(evtIdx, event) {\n            var link = $(event).find('a[data-action=\"view-event\"]');\n            var title = link.attr('title');\n            link.attr('title', $('<textarea />').html(title).text()); // JS equivalent of PHP html_entity_decode\n        });\n    };\n\n    // Mark RWTHonline events as such and remove edit/delete buttons from day view.\n    var fixDayView = function() {\n        $(\".eventlist .event\").each(function(evtIdx, event) {\n            var eventid = $(event).attr('data-event-id');\n\n            // Check if the event shoud be rendered as a RWTHonline event.\n            ifRenderAsRWTHonlineEvent(eventid, function() {\n\n                // Replace command buttons with text.\n                var commands = $(event).find('.commands');\n                if (commands.find(\".rwthonline_event_info_rendered\").length) {\n                    // Command buttons already replaced.\n                    return;\n                }\n                Str.get_string('rwthonline_event_help', 'local_rwth_sd_sync').done(function(localizedString) {\n                    Ajax.call([\n                        {methodname: 'local_rwth_sd_sync_get_rwthonline_event_url', args: {\n                            id: eventid\n                        }}\n                    ])[0].done(function(rwthonlineurl) {\n                        Templates.render('local_rwth_sd_sync/rwthonline_event_info_day',\n                                {rwthonlineurl: rwthonlineurl, text: localizedString}).done(function(rwthonlineInfo) {\n                            commands.empty().append(rwthonlineInfo);\n                        });\n                    }).fail(Notification.exception);\n                });\n            });\n        });\n    };\n\n    // Prevent drag-and-drop.\n    var preventDrag = function() {\n        var rwthonlineEvents = $(\"[data-eventtype-rwthonline='1']\");\n        rwthonlineEvents.on(\"dragstart\", function(event) {\n            event.stopImmediatePropagation();\n            var target = $(event.target);\n\n            Str.get_string('rwthonline_event_tooltip_drag', 'local_rwth_sd_sync').done(function(localizedString) {\n\n                // Store title in another attribute.\n                var title = target.attr('title');\n                target.attr('actual-original-title', title);\n\n                // Show tooltip.\n                target.attr('title', localizedString);\n                target.tooltip({\n                    container: \"body\",\n                    trigger: \"manual\",\n                    html: true,\n                    template: '<div class=\"tooltip error\" role=\"tooltip\">'\n                        + '<div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n                });\n                target.tooltip('enable');\n                target.tooltip('show');\n            });\n\n        });\n        rwthonlineEvents.on(\"dragend\", function(event) {\n            event.stopImmediatePropagation();\n            var target = $(event.target);\n\n            // Delay hiding the tootip slightly.\n            setTimeout(function() {\n                // Hide tooltip.\n                target.tooltip('hide');\n                target.tooltip('disable');\n\n                // Restore title.\n                var title = target.attr('actual-original-title');\n                target.attr('title', title);\n            }, 300);\n        });\n    };\n\n    return {\n        init: function() {\n\n            // Load Boost tooltips.\n            require(['theme_boost/loader']);\n\n            $(document).ready(function() {\n                fixModal();\n                preventDrag();\n            });\n            $('body').on(CalendarEvents.viewUpdated, function() {\n                fixMonthView();\n                fixDayView();\n                preventDrag();\n            });\n        }\n    };\n});"],"names":["define","$","Ajax","Notification","Str","Templates","CalendarEvents","ifRenderAsRWTHonlineEvent","eventid","then","cachedValue","cache","localStorage","getItem","JSON","parse","cacheGetRenderAsRWTHonlineEvent","undefined","call","methodname","args","id","done","renderAsRWTHonlineEvent","value","setItem","stringify","cacheSetRenderAsRWTHonlineEvent","fail","exception","preventDrag","rwthonlineEvents","on","event","stopImmediatePropagation","target","get_string","localizedString","title","attr","tooltip","container","trigger","html","template","setTimeout","init","require","document","ready","targetNode","getElementById","observer","MutationObserver","mutationsList","forEach","mutation","addedNodes","node","nodeName","innerHTML","childNodes","length","observe","childList","dialog","classList","contains","querySelector","summaryContainer","getAttribute","footer","rwthonlineurl","render","text","rwthonlineInfo","remove","ex","fixModal","viewUpdated","each","evtIdx","link","find","commands","empty","append"],"mappings":"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"}
\ No newline at end of file
diff --git a/amd/src/RWTHonlineEvents.js b/amd/src/RWTHonlineEvents.js
index ab7e33e215c720bc241f9467d17fad144aab757c..600d7ca24c4e32c3a7e41af70b1534b4960a6067 100644
--- a/amd/src/RWTHonlineEvents.js
+++ b/amd/src/RWTHonlineEvents.js
@@ -90,52 +90,59 @@ define([
         }
         var config = { childList: true };
         var callback = function(mutationsList) {
-            $.each(mutationsList, function(mutIdx, mutation) {
+            mutationsList.forEach(function(mutation) {
                 if (mutation == 0) {
                     return true;
                 }
-                $.each(mutation.addedNodes, function(nodeIdx, node) {
-                    var dialog = $(node).find('.modal-dialog');
-                    if (!dialog.length) {
+                mutation.addedNodes.forEach(function(node) {
+                    if (node.nodeName == "DIV" && node.innerHTML == "" && node.childNodes.length == 0) {
+                        observer.observe(node, {childList: true});
+                        return true;
+                    }
+                    var dialog = node.classList.contains('summary-modal-container') ?
+                        document.querySelector('#page-calendar-view .modal-dialog') : node.querySelector('.modal-dialog');
+                    var summaryContainer = node.classList.contains('summary-modal-container') ?
+                        node : node.querySelector('.modal-body .summary-modal-container');
+
+                    if (!dialog && !summaryContainer) {
                         // Not a modal dialog.
                         return true;
                     }
 
-                    var summaryContainer = dialog.find('.modal-body .summary-modal-container');
-                    if (!summaryContainer.length) {
-                        // Not the modal content we are looking for.
+                    if (dialog && !summaryContainer) {
+                        // Modal body is loaded but content still loading, await insertion of content block
+                        observer.observe(node.querySelector('.modal-body'), {childList: true});
                         return true;
                     }
 
-                    var eventid = summaryContainer.attr('data-event-id');
+                    var eventid = summaryContainer.getAttribute('data-event-id');
                     ifRenderAsRWTHonlineEvent(eventid, function() {
-                        // Replace icon (the icon in the first <div> of the last row).
-                        var eventicon = $(summaryContainer).find('.fa-university');
-                        var eventicontitle = eventicon.attr("title");
-                        var eventiconcol = eventicon.parent();
-                        eventiconcol.empty();
-                        Templates.render('local_rwth_sd_sync/rwthonline_event_icon',
-                                {'title': eventicontitle}).done(function(icon) {
-                            eventiconcol.append(icon);
-                        });
 
-                        // Remove edit/delete buttons.
-                        var footer = dialog.find('.modal-footer');
-                        if (footer.find(".rwthonline_event_info_rendered").length) {
-                            // Edit/delete buttons already removed.
-                            return;
+                        // Do not render twice
+                        var footer = dialog.querySelector('.modal-footer');
+                        if (footer.querySelector(".rwthonline_event_info_rendered")) {
+                            // Already rendered
+                            return true;
                         }
+
                         Str.get_string('rwthonline_event_help', 'local_rwth_sd_sync').done(function(localizedString) {
-                            Ajax.call([
-                                {methodname: 'local_rwth_sd_sync_get_rwthonline_event_url', args: {
+                            Ajax.call([{
+                                methodname: 'local_rwth_sd_sync_get_rwthonline_event_url',
+                                args: {
                                     id: eventid
-                                }}
-                            ])[0].done(function(rwthonlineurl) {
-                                Templates.render('local_rwth_sd_sync/rwthonline_event_info_modal',
-                                        {rwthonlineurl: rwthonlineurl, text: localizedString}).done(function(rwthonlineInfo) {
-                                    footer.empty().append(rwthonlineInfo);
-                                });
-                            }).fail(Notification.exception);
+                                },
+                                done: function(rwthonlineurl) {
+                                    Templates.render('local_rwth_sd_sync/rwthonline_event_info_modal',
+                                        {rwthonlineurl: rwthonlineurl, text: localizedString})
+                                    .done(function(rwthonlineInfo) {
+                                        footer.innerHTML = rwthonlineInfo;
+                                        footer.classList.remove("hidden");
+                                    });
+                                },
+                                fail: function(ex) {
+                                    Notification.exception(ex);
+                                },
+                            }]);
                         });
                     });
                 });
@@ -149,25 +156,8 @@ define([
     var fixMonthView = function() {
         $('[data-region="event-item"]').each(function(evtIdx, event) {
             var link = $(event).find('a[data-action="view-event"]');
-            var eventid = link.attr('data-event-id');
             var title = link.attr('title');
             link.attr('title', $('<textarea />').html(title).text()); // JS equivalent of PHP html_entity_decode
-
-            ifRenderAsRWTHonlineEvent(eventid, function() {
-                // Mark as a rwthonline event, e.g. for drag-and-drop handling.
-                $(event).attr('data-eventtype-rwthonline', '1');
-
-                // Replace icon.
-                if ($(event).find(".rwthonline_event_icon_rendered").length) {
-                    // Icon already replaced.
-                    return;
-                }
-                var eventicon = $(event).find('i.fa-university, i.fa-group');
-                Templates.render('local_rwth_sd_sync/rwthonline_event_icon', {}).done(function(icon) {
-                    icon = icon.replace(' alt=""', '').replace(' title=""', '');
-                    eventicon.replaceWith(icon);
-                });
-            });
         });
     };
 
@@ -178,11 +168,6 @@ define([
 
             // Check if the event shoud be rendered as a RWTHonline event.
             ifRenderAsRWTHonlineEvent(eventid, function() {
-                // Replace icon.
-                var eventicon = $(event).find('i.fa-university');
-                Templates.render('local_rwth_sd_sync/rwthonline_event_icon', {}).done(function(icon) {
-                    eventicon.replaceWith(icon);
-                });
 
                 // Replace command buttons with text.
                 var commands = $(event).find('.commands');
diff --git a/classes/output/core_calendar_renderer.php b/classes/output/core_calendar_renderer.php
index 509f7441d1a2c95293d5a2acafeb2d79b67fba0d..03379498dddb137451629121525f9b7c4bef5d3b 100644
--- a/classes/output/core_calendar_renderer.php
+++ b/classes/output/core_calendar_renderer.php
@@ -47,6 +47,10 @@ class core_calendar_renderer extends \core_calendar_renderer {
                 return 'local_rwth_sd_sync/calendar_month';
             case 'core_calendar/calendar_day':
                 return 'local_rwth_sd_sync/calendar_day';
+            case 'core_calendar/month_detailed':
+                return 'local_rwth_sd_sync/month_detailed';
+            case 'core_calendar/day_detailed':
+                return 'local_rwth_sd_sync/day_detailed';
         }
         return $originalname;
     }
@@ -64,6 +68,12 @@ class core_calendar_renderer extends \core_calendar_renderer {
             case 'core_calendar/calendar_day':
                 $this->calendar_day_override($args);
                 break;
+            case 'core_calendar/month_detailed':
+                $this->calendar_month_override($args);
+                break;
+            case 'core_calendar/day_detailed':
+                $this->calendar_day_override($args);
+                break;
         }
         return $args;
     }
@@ -97,12 +107,6 @@ class core_calendar_renderer extends \core_calendar_renderer {
                 // Make event not editable/deletable.
                 $event->canedit = false;
                 $event->candelete = false;
-
-                // Replace the default course event icon with a rwthonline icon, but only for
-                // managers in the course that this event belongs to.
-                $event->icon->key = 'i/rwthonline';
-                $event->icon->component = 'local_rwth_sd_sync';
-                $event->icon->alttext = get_string('rwthonline_icon_alt', 'local_rwth_sd_sync');
             }
         }
     }
diff --git a/lang/de/local_rwth_sd_sync.php b/lang/de/local_rwth_sd_sync.php
index a3d9e0acaec17417d688d07817e07b09450f850f..a970ce80fbf3fb06d0bacf61f6873306be59f48b 100644
--- a/lang/de/local_rwth_sd_sync.php
+++ b/lang/de/local_rwth_sd_sync.php
@@ -19,5 +19,7 @@ $string['privacy:metadata'] = 'Dieses Plugin synchronisiert nur Daten von einer
 $string['in_rwthonline_postfix'] = '(in RWTHonline)';
 $string['rwthonline_event_tooltip_drag'] = '<i class="fa fa-ban" aria-hidden="true"></i> Bearbeiten dieses Termins ist<br />nur in RWTHonline möglich.';
 $string['rwthonline_icon_alt'] = 'RWTHonline-Termin';
+$string['course'] = 'RWTHonline-Kurstermin';
+$string['group'] = 'RWTHonline-Gruppentermin';
 $string['rwthonline_event_help'] = 'Dieser Termin wird automatisch aus RWTHonline übernommen. Er kann nur dort bearbeitet oder gelöscht werden. In RWTHonline vorgenommene Änderungen werden alle 15 Minuten automatisch nach RWTHmoodle synchronisiert.';
-$string['synctask'] = 'Kurse, Gruppen und Termine synchronisieren';
\ No newline at end of file
+$string['synctask'] = 'Kurse, Gruppen und Termine synchronisieren';
diff --git a/lang/en/local_rwth_sd_sync.php b/lang/en/local_rwth_sd_sync.php
index 85d00fc7ec7c06cabe56c363b3b2c6f8e54c2a54..ea8dc3b1b0584c827ff75c230656847097cf18b1 100644
--- a/lang/en/local_rwth_sd_sync.php
+++ b/lang/en/local_rwth_sd_sync.php
@@ -125,5 +125,7 @@ $string['privacy:metadata'] = 'This plugin only synchronizes data from an extern
 $string['in_rwthonline_postfix'] = '(in RWTHonline)';
 $string['rwthonline_event_tooltip_drag'] = '<i class="fa fa-ban" aria-hidden="true"></i> Event can only be<br />edited in RWTHonline.';
 $string['rwthonline_icon_alt'] = 'RWTHonline event';
+$string['course'] = 'RWTHonline course event';
+$string['group'] = 'RWTHonline group event';
 $string['rwthonline_event_help'] = 'This date is automatically synchronized from RWTHonline. Editing or deleting has to be done there. All changes made in RWTHonline will be synchronized to RWTHmoodle every 15 minutes.';
-$string['synctask'] = 'Sync courses, groups and appointments';
\ No newline at end of file
+$string['synctask'] = 'Sync courses, groups and appointments';
diff --git a/pix/i/rwthonline.png b/pix/course.png
similarity index 100%
rename from pix/i/rwthonline.png
rename to pix/course.png
diff --git a/pix/group.png b/pix/group.png
new file mode 100644
index 0000000000000000000000000000000000000000..9bccf8c87382f61c490cb41e084cd88b88d6e958
Binary files /dev/null and b/pix/group.png differ
diff --git a/templates/calendar_day.mustache b/templates/calendar_day.mustache
index 7fa4ce8dba71329be79aab0f1fa9c3d13be6a1da..3e16a0154ff170c405cda548c0d6ec7ff2415840 100644
--- a/templates/calendar_day.mustache
+++ b/templates/calendar_day.mustache
@@ -32,6 +32,7 @@
     }
 }}
 <div id="calendar-day-{{uniqid}}" data-template="core_calendar/day_detailed">
+    {{> core_calendar/header}}
     {{> local_rwth_sd_sync/day_detailed}}
 </div>
 {{#js}}
@@ -47,4 +48,4 @@ require([
     CalendarView.init($("#calendar-day-{{uniqid}}"), 'day');
     RWTHonlineEvents.init();
 });
-{{/js}}
\ No newline at end of file
+{{/js}}
diff --git a/templates/calendar_day.mustache.original b/templates/calendar_day.mustache.original
index 7d75b5779f653da943473791402c66c2241c927e..e9ffd4375a8984704d258962fa84358502a8f6aa 100644
--- a/templates/calendar_day.mustache.original
+++ b/templates/calendar_day.mustache.original
@@ -15,7 +15,7 @@
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 }}
 {{!
-    @template calendar/calendar_day
+    @template core_calendar/calendar_day
 
     Calendar day view.
 
@@ -32,6 +32,7 @@
     }
 }}
 <div id="calendar-day-{{uniqid}}" data-template="core_calendar/day_detailed">
+    {{> core_calendar/header}}
     {{> core_calendar/day_detailed}}
 </div>
 {{#js}}
diff --git a/templates/calendar_month.mustache b/templates/calendar_month.mustache
index 0683b33e85e25233a8228135ba0b778425148a90..b9430f396f38c00f8da678baa5e4088aef24485d 100644
--- a/templates/calendar_month.mustache
+++ b/templates/calendar_month.mustache
@@ -17,7 +17,7 @@
 {{!
     @template local_rwth_sd_sync/calendar_month
 
-    Calendar month view for blocks.
+    Calendar month view for blcoks.
 
     The purpose of this template is to render the main, detailed monthly view.
 
@@ -32,6 +32,7 @@
     }
 }}
 <div id="calendar-month-{{uniqid}}" data-template="core_calendar/month_detailed">
+    {{> core_calendar/header}}
     {{> local_rwth_sd_sync/month_detailed}}
 </div>
 {{#js}}
@@ -47,4 +48,4 @@ require([
     Calendar.init($("#calendar-month-{{uniqid}}"));
     RWTHonlineEvents.init();
 });
-{{/js}}
\ No newline at end of file
+{{/js}}
diff --git a/templates/calendar_month.mustache.original b/templates/calendar_month.mustache.original
index 9e5866b68be3a4510642b73e3f555290370b82a0..1e83271d41dbbf51c35f18db94ceb8e7ed1d5b4f 100644
--- a/templates/calendar_month.mustache.original
+++ b/templates/calendar_month.mustache.original
@@ -32,6 +32,7 @@
     }
 }}
 <div id="calendar-month-{{uniqid}}" data-template="core_calendar/month_detailed">
+    {{> core_calendar/header}}
     {{> core_calendar/month_detailed}}
 </div>
 {{#js}}
diff --git a/templates/day_detailed.mustache b/templates/day_detailed.mustache
index 51993e33632a2b163bbc58096ab45f225ca8d86c..95232dcff9051bce43f461cf382e9a42c5790a4c 100644
--- a/templates/day_detailed.mustache
+++ b/templates/day_detailed.mustache
@@ -43,8 +43,11 @@
     }} data-region="day"{{!
     }} data-new-event-timestamp="{{neweventtimestamp}}"{{!
 }}>
-    {{> core_calendar/header}}
     {{> core_calendar/day_navigation }}
     {{> core/overlay_loading}}
-    {{> local_rwth_sd_sync/event_list }}
+    {{< local_rwth_sd_sync/event_list }}
+        {{$noeventsmessage}}
+            {{#str}} daywithnoevents, core_calendar {{/str}}
+        {{/noeventsmessage}}
+    {{/local_rwth_sd_sync/event_list}}
 </div>
diff --git a/templates/day_detailed.mustache.original b/templates/day_detailed.mustache.original
index 74d48bb43424036c5acd67d8b36796f26a811d93..2148170c1fe9f116a1c4e1128750af2405916788 100644
--- a/templates/day_detailed.mustache.original
+++ b/templates/day_detailed.mustache.original
@@ -15,7 +15,7 @@
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 }}
 {{!
-    @template calendar/day_detailed
+    @template core_calendar/day_detailed
 
     Calendar day view.
 
@@ -43,8 +43,11 @@
     }} data-region="day"{{!
     }} data-new-event-timestamp="{{neweventtimestamp}}"{{!
 }}>
-    {{> core_calendar/header}}
     {{> core_calendar/day_navigation }}
     {{> core/overlay_loading}}
-    {{> core_calendar/event_list }}
+    {{< core_calendar/event_list }}
+        {{$noeventsmessage}}
+            {{#str}} daywithnoevents, core_calendar {{/str}}
+        {{/noeventsmessage}}
+    {{/core_calendar/event_list}}
 </div>
diff --git a/templates/event_icon.mustache b/templates/event_icon.mustache
deleted file mode 100644
index 40f7f7e676876b87f9d436e8ee9b529d44d72c86..0000000000000000000000000000000000000000
--- a/templates/event_icon.mustache
+++ /dev/null
@@ -1,46 +0,0 @@
-{{!
-    This file is part of Moodle - http://moodle.org/
-
-    Moodle is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    Moodle is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-}}
-{{!
-    @template local_rwth_sd_sync/event_icon
-
-    Event icon display.
-
-    The purpose of this template is to provide a common location for the
-    rendering of event icons.
-
-    Classes required for JS:
-    * none
-
-    Data attributes required for JS:
-    * none
-
-    Example context (json):
-    {
-        "modulename": "assign"
-    }
-}}
-{{#modulename}}
-    {{#pix}} icon, {{modulename}} {{/pix}}
-{{/modulename}}
-{{^modulename}}
-    {{#isrwthonlineevent}}
-        {{> local_rwth_sd_sync/rwthonline_event_icon}}
-    {{/isrwthonlineevent}}
-    {{^isrwthonlineevent}}
-        {{#pix}} i/{{eventtype}}event, core {{/pix}}
-    {{/isrwthonlineevent}}
-{{/modulename}}
diff --git a/templates/event_icon.mustache.original b/templates/event_icon.mustache.original
deleted file mode 100644
index fb88bd6c6eab1747d6941084a8888beb899db71b..0000000000000000000000000000000000000000
--- a/templates/event_icon.mustache.original
+++ /dev/null
@@ -1,41 +0,0 @@
-{{!
-    This file is part of Moodle - http://moodle.org/
-
-    Moodle is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    Moodle is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-}}
-{{!
-    @template calendar/event_icon
-
-    Event icon display.
-
-    The purpose of this template is to provide a common location for the
-    rendering of event icons.
-
-    Classes required for JS:
-    * none
-
-    Data attributes required for JS:
-    * none
-
-    Example context (json):
-    {
-        "modulename": "assign"
-    }
-}}
-{{#modulename}}
-    {{#pix}} icon, {{modulename}} {{/pix}}
-{{/modulename}}
-{{^modulename}}
-    {{#pix}} i/{{eventtype}}event, core {{/pix}}
-{{/modulename}}
diff --git a/templates/event_item.mustache b/templates/event_item.mustache
index de901a2e7652d3946db0c87f85bbd6559c4ae274..7bd606a5f95f82268d08d60cf9e355c4a420f555 100644
--- a/templates/event_item.mustache
+++ b/templates/event_item.mustache
@@ -29,20 +29,38 @@
 
     Example context (json):
     {
+        "id": 1,
+        "name": "Sample event name",
+        "normalisedeventtype": "course",
+        "course": {
+            "id": 1
+        },
+        "canedit": true,
+        "candelete": true,
+        "isactionevent": true,
+        "icon": {
+            "key": "i/courseevent",
+            "component": "core",
+            "alttext": "Some course event"
+        },
+        "editurl": "#",
+        "url": "#"
     }
 }}
 <div{{!
     }} data-type="event"{{!
     }} data-course-id="{{course.id}}"{{!
     }} data-event-id="{{id}}"{{!
-    }} class="event"{{!
+    }} class="event mt-3"{{!
+    }} data-event-component="{{component}}"{{!
+    }} data-event-eventtype="{{eventtype}}"{{!
     }} data-eventtype-{{normalisedeventtype}}="1"{{!
-    }} data-event-title="{{name}}"{{!
+    }} data-event-title="{{title}}"{{!
     }} data-event-count="{{eventcount}}"{{!
     }}>
-    <div class="card">
-        <div class="box card-header clearfix p-y-1">
-            <div class="commands pull-xs-right">
+    <div class="card rounded">
+        <div class="box card-header clearfix calendar_event_{{normalisedeventtype}}">
+            <div class="commands float-sm-right">
                 {{#isrwthonlineevent}}
                     {{> local_rwth_sd_sync/rwthonline_event_info_day}}
                 {{/isrwthonlineevent}}
@@ -53,29 +71,33 @@
                                 {{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}
                             </a>
                         {{/candelete}}
-                        <a href="{{editurl}}" data-action="edit">
-                            {{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}
-                        </a>
+                        {{^isactionevent}}
+                            <a href="{{editurl}}" data-action="edit">
+                                {{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}
+                            </a>
+                        {{/isactionevent}}
                     {{/canedit}}
                 {{/isrwthonlineevent}}
             </div>
-            {{#icon}}{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}{{/icon}}
-            <h3 class="name d-inline-block">{{title}}</h3>
-            <span class="date pull-xs-right m-r-1">{{{formattedtime}}}</span>
+            {{#icon}}<div class="d-inline-block mt-1 align-top">{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}</div>{{/icon}}
+            <div class="d-inline-block">
+                <h3 class="name d-inline-block">{{{name}}}</h3>
+            </div>
+        </div>
+        <div class="description card-body">
+            {{> core_calendar/event_details }}
         </div>
-        <div class="description card-block calendar_event_{{eventtype}}">
-            <p>{{{description}}}</p>
-            {{#iscourseevent}}
-                <div><a href="{{url}}">{{course.fullname}}</a></div>
-            {{/iscourseevent}}
-            {{> core_calendar/event_subscription}}
+        {{#action.actionable}}
+            <div class="card-footer text-right bg-transparent">
+                <a href="{{action.url}}" class="card-link">{{{action.name}}}</a>
+            </div>
+        {{/action.actionable}}
+        {{^action.actionable}}
             {{#isactionevent}}
-                <a href="{{url}}">{{#str}} gotoactivity, core_calendar {{/str}}</a>
+            <div class="card-footer text-right bg-transparent">
+                <a href="{{url}}" class="card-link">{{#str}} gotoactivity, core_calendar {{/str}}</a>
+            </div>
             {{/isactionevent}}
-            {{#groupname}}
-                <div><a href="{{url}}">{{{course.fullname}}}</a></div>
-                <div>{{{groupname}}}</div>
-            {{/groupname}}
-        </div>
+        {{/action.actionable}}
     </div>
 </div>
diff --git a/templates/event_item.mustache.original b/templates/event_item.mustache.original
index 91d075198876c139282021f129ea9639fbb51c5d..3920e03c33434bb5d6abca91395525be618490c9 100644
--- a/templates/event_item.mustache.original
+++ b/templates/event_item.mustache.original
@@ -15,7 +15,7 @@
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 }}
 {{!
-    @template calendar/event_item
+    @template core_calendar/event_item
 
     Calendar event item.
 
@@ -29,48 +29,70 @@
 
     Example context (json):
     {
+        "id": 1,
+        "name": "Sample event name",
+        "normalisedeventtype": "course",
+        "course": {
+            "id": 1
+        },
+        "canedit": true,
+        "candelete": true,
+        "isactionevent": true,
+        "icon": {
+            "key": "i/courseevent",
+            "component": "core",
+            "alttext": "Some course event"
+        },
+        "editurl": "#",
+        "url": "#"
     }
 }}
 <div{{!
     }} data-type="event"{{!
     }} data-course-id="{{course.id}}"{{!
     }} data-event-id="{{id}}"{{!
-    }} class="event"{{!
-    }} data-eventtype-{{calendareventtype}}="1"{{!
+    }} class="event mt-3"{{!
+    }} data-event-component="{{component}}"{{!
+    }} data-event-eventtype="{{eventtype}}"{{!
+    }} data-eventtype-{{normalisedeventtype}}="1"{{!
     }} data-event-title="{{name}}"{{!
     }} data-event-count="{{eventcount}}"{{!
     }}>
-    <div class="card">
-        <div class="box card-header clearfix p-y-1">
-            <div class="commands pull-xs-right">
+    <div class="card rounded">
+        <div class="box card-header clearfix calendar_event_{{normalisedeventtype}}">
+            <div class="commands float-sm-right">
                 {{#canedit}}
                     {{#candelete}}
                         <a href="{{deleteurl}}" data-action="delete">
                             {{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}
                         </a>
                     {{/candelete}}
-                    <a href="{{editurl}}" data-action="edit">
-                        {{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}
-                    </a>
+                    {{^isactionevent}}
+                        <a href="{{editurl}}" data-action="edit">
+                            {{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}
+                        </a>
+                    {{/isactionevent}}
                 {{/canedit}}
             </div>
-            {{#icon}}{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}{{/icon}}
-            <h3 class="name d-inline-block">{{name}}</h3>
-            <span class="date pull-xs-right m-r-1">{{{formattedtime}}}</span>
+            {{#icon}}<div class="d-inline-block mt-1 align-top">{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}</div>{{/icon}}
+            <div class="d-inline-block">
+                <h3 class="name d-inline-block">{{{name}}}</h3>
+            </div>
+        </div>
+        <div class="description card-body">
+            {{> core_calendar/event_details }}
         </div>
-        <div class="description card-block calendar_event_{{eventtype}}">
-            <p>{{{description}}}</p>
-            {{#iscourseevent}}
-                <div><a href="{{url}}">{{course.fullname}}</a></div>
-            {{/iscourseevent}}
-            {{> core_calendar/event_subscription}}
+        {{#action.actionable}}
+            <div class="card-footer text-right bg-transparent">
+                <a href="{{action.url}}" class="card-link">{{{action.name}}}</a>
+            </div>
+        {{/action.actionable}}
+        {{^action.actionable}}
             {{#isactionevent}}
-                <a href="{{url}}">{{#str}} gotoactivity, core_calendar {{/str}}</a>
+            <div class="card-footer text-right bg-transparent">
+                <a href="{{url}}" class="card-link">{{#str}} gotoactivity, core_calendar {{/str}}</a>
+            </div>
             {{/isactionevent}}
-            {{#groupname}}
-                <div><a href="{{url}}">{{{course.fullname}}}</a></div>
-                <div>{{{groupname}}}</div>
-            {{/groupname}}
-        </div>
+        {{/action.actionable}}
     </div>
 </div>
diff --git a/templates/event_list.mustache b/templates/event_list.mustache
index 69226ab877ff71a49036323f13cbee310d17f127..2cffd0db2713f27cecb22767b00bbc768d5ec9fb 100644
--- a/templates/event_list.mustache
+++ b/templates/event_list.mustache
@@ -31,13 +31,13 @@
     {
     }
 }}
-<div class="eventlist m-y-1">
+<div class="eventlist my-1">
     {{#events}}
         {{> local_rwth_sd_sync/event_item }}
     {{/events}}
     {{^events}}
         <span class="calendar-information calendar-no-results">
-            {{#str}}daywithnoevents, calendar{{/str}}
+            {{$noeventsmessage}}{{/noeventsmessage}}
         </span>
     {{/events}}
 </div>
\ No newline at end of file
diff --git a/templates/event_list.mustache.original b/templates/event_list.mustache.original
index 7b6f28d1aae4b2995254d16ba900a17c70e0f99c..63e4ca91709c60a4c7cb6c31c573db4fe7441045 100644
--- a/templates/event_list.mustache.original
+++ b/templates/event_list.mustache.original
@@ -15,7 +15,7 @@
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 }}
 {{!
-    @template calendar/event_list
+    @template core_calendar/event_list
 
     Calendar event list.
 
@@ -31,13 +31,13 @@
     {
     }
 }}
-<div class="eventlist m-y-1">
+<div class="eventlist my-1">
     {{#events}}
         {{> core_calendar/event_item }}
     {{/events}}
     {{^events}}
         <span class="calendar-information calendar-no-results">
-            {{#str}}daywithnoevents, calendar{{/str}}
+            {{$noeventsmessage}}{{/noeventsmessage}}
         </span>
     {{/events}}
 </div>
\ No newline at end of file
diff --git a/templates/month_detailed.mustache b/templates/month_detailed.mustache
index 9d58ce8fa324c32f20fa8652a0c9b4d2b24b222a..ee592149a8154ac835e2cdbd88af8a5dbba60f14 100644
--- a/templates/month_detailed.mustache
+++ b/templates/month_detailed.mustache
@@ -40,15 +40,15 @@
     }} data-year="{{date.year}}"{{!
     }} data-view="month"{{!
     }}>
-    {{> core_calendar/header }}
     {{> core_calendar/month_navigation }}
     {{> core/overlay_loading}}
-    <table id="month-detailed-{{uniqid}}" class="calendarmonth calendartable m-b-0">
+    <table id="month-detailed-{{uniqid}}" class="calendarmonth calendartable mb-0">
         <thead>
             <tr>
                 {{# daynames }}
                 <th class="header text-xs-center">
-                    {{shortname}}
+                    <span class="sr-only">{{fullname}}</span>
+                    <span aria-hidden="true">{{shortname}}</span>
                 </th>
                 {{/ daynames }}
             </tr>
@@ -72,21 +72,27 @@
                         data-region="day"
                         data-new-event-timestamp="{{neweventtimestamp}}">
                         <div class="d-none d-md-block hidden-phone text-xs-center">
+                            <span class="sr-only">{{daytitle}}</span>
                             {{#hasevents}}
-                                <a data-action="view-day-link" href="{{viewdaylink}}" class="day" title="{{viewdaylinktitle}}">{{mday}}</a>
+                                <a data-action="view-day-link" href="#" class="aalink day" aria-label="{{viewdaylinktitle}}"
+                                    data-year="{{date.year}}" data-month="{{date.mon}}" data-day="{{mday}}"
+                                    data-courseid="{{courseid}}" data-categoryid="{{categoryid}}"
+                                    data-timestamp="{{timestamp}}">{{mday}}</a>
                             {{/hasevents}}
                             {{^hasevents}}
-                                {{mday}}
+                                <span aria-hidden="true">{{mday}}</span>
                             {{/hasevents}}
                             {{#hasevents}}
                                 <div data-region="day-content">
                                     <ul>
                                         {{#events}}
                                         {{#underway}}
-                                            <li class="events-underway">[{{name}}]</li>
+                                            <li class="events-underway">[{{{name}}}]</li>
                                         {{/underway}}
                                         {{^underway}}
                                             <li data-region="event-item"
+                                                data-event-component="{{component}}"
+                                                data-event-eventtype="{{eventtype}}"
                                                 data-eventtype-{{normalisedeventtype}}="1"
                                                 {{#isrwthonlineevent}}
                                                     data-eventtype-rwthonline="1"
@@ -109,11 +115,11 @@
                                                 {{/draggable}}>
 
                                                 <a data-action="view-event" data-event-id="{{id}}" href="{{url}}" title="{{title}}">
-                                                    <span class="badge badge-circle calendar_event_{{normalisedeventtype}}">
+                                                    <span class="calendar-circle calendar_event_{{normalisedeventtype}}">
                                                         &nbsp;
                                                     </span>
-                                                    {{> local_rwth_sd_sync/event_icon}}
-                                                    <span class="eventname">{{title}}</span>
+                                                    {{> core_calendar/event_icon}}
+                                                    <span class="eventname">{{{name}}}</span>
                                                 </a>
                                             </li>
                                         {{/underway}}
@@ -123,13 +129,15 @@
                             {{/hasevents}}
                         </div>
                         <div class="d-md-none hidden-desktop hidden-tablet">
+                            <span class="sr-only">{{daytitle}}</span>
                             {{#hasevents}}
-                                <a data-action="view-day-link" href="{{viewdaylink}}" class="day" title="{{viewdaylinktitle}}">{{mday}}</a>
+                                <a data-action="view-day-link" href="#" class="day aalink" aria-label="{{viewdaylinktitle}}"
+                                    data-year="{{date.year}}" data-month="{{date.mon}}" data-day="{{mday}}"
+                                    data-courseid="{{courseid}}" data-categoryid="{{categoryid}}"
+                                    data-timestamp="{{timestamp}}">{{mday}}</a>
                             {{/hasevents}}
                             {{^hasevents}}
-                                <div data-region="day-content">
-                                    {{mday}}
-                                </div>
+                                <span aria-hidden="true">{{mday}}</span>
                             {{/hasevents}}
                         </div>
                     </td>
diff --git a/templates/month_detailed.mustache.original b/templates/month_detailed.mustache.original
index 9231fa8a6ead2ce57b0f64e586e3973a063a19f1..201e6da009bbe3e688515ad64e03650b6b8a0daa 100644
--- a/templates/month_detailed.mustache.original
+++ b/templates/month_detailed.mustache.original
@@ -40,15 +40,15 @@
     }} data-year="{{date.year}}"{{!
     }} data-view="month"{{!
     }}>
-    {{> core_calendar/header }}
     {{> core_calendar/month_navigation }}
     {{> core/overlay_loading}}
-    <table id="month-detailed-{{uniqid}}" class="calendarmonth calendartable m-b-0">
+    <table id="month-detailed-{{uniqid}}" class="calendarmonth calendartable mb-0">
         <thead>
             <tr>
                 {{# daynames }}
                 <th class="header text-xs-center">
-                    {{shortname}}
+                    <span class="sr-only">{{fullname}}</span>
+                    <span aria-hidden="true">{{shortname}}</span>
                 </th>
                 {{/ daynames }}
             </tr>
@@ -72,22 +72,28 @@
                         data-region="day"
                         data-new-event-timestamp="{{neweventtimestamp}}">
                         <div class="d-none d-md-block hidden-phone text-xs-center">
+                            <span class="sr-only">{{daytitle}}</span>
                             {{#hasevents}}
-                                <a data-action="view-day-link" href="{{viewdaylink}}" class="day" title="{{viewdaylinktitle}}">{{mday}}</a>
+                                <a data-action="view-day-link" href="#" class="aalink day" aria-label="{{viewdaylinktitle}}"
+                                    data-year="{{date.year}}" data-month="{{date.mon}}" data-day="{{mday}}"
+                                    data-courseid="{{courseid}}" data-categoryid="{{categoryid}}"
+                                    data-timestamp="{{timestamp}}">{{mday}}</a>
                             {{/hasevents}}
                             {{^hasevents}}
-                                {{mday}}
+                                <span aria-hidden="true">{{mday}}</span>
                             {{/hasevents}}
                             {{#hasevents}}
                                 <div data-region="day-content">
                                     <ul>
                                         {{#events}}
                                         {{#underway}}
-                                            <li class="events-underway">[{{name}}]</li>
+                                            <li class="events-underway">[{{{name}}}]</li>
                                         {{/underway}}
                                         {{^underway}}
                                             <li data-region="event-item"
-                                                data-eventtype-{{calendareventtype}}="1"
+                                                data-event-component="{{component}}"
+                                                data-event-eventtype="{{eventtype}}"
+                                                data-eventtype-{{normalisedeventtype}}="1"
                                                 {{#draggable}}
                                                     draggable="true"
                                                     data-drag-type="move"
@@ -105,12 +111,12 @@
                                                     {{/maxdayerror}}
                                                 {{/draggable}}>
 
-                                                <a data-action="view-event" data-event-id="{{id}}" href="{{url}}" title="{{name}}">
-                                                    <span class="badge badge-circle calendar_event_{{calendareventtype}}">
+                                                <a data-action="view-event" data-event-id="{{id}}" href="{{url}}" title="{{title}}">
+                                                    <span class="calendar-circle calendar_event_{{normalisedeventtype}}">
                                                         &nbsp;
                                                     </span>
                                                     {{> core_calendar/event_icon}}
-                                                    <span class="eventname">{{name}}</span>
+                                                    <span class="eventname">{{{name}}}</span>
                                                 </a>
                                             </li>
                                         {{/underway}}
@@ -120,13 +126,15 @@
                             {{/hasevents}}
                         </div>
                         <div class="d-md-none hidden-desktop hidden-tablet">
+                            <span class="sr-only">{{daytitle}}</span>
                             {{#hasevents}}
-                                <a data-action="view-day-link" href="{{viewdaylink}}" class="day" title="{{viewdaylinktitle}}">{{mday}}</a>
+                                <a data-action="view-day-link" href="#" class="day aalink" aria-label="{{viewdaylinktitle}}"
+                                    data-year="{{date.year}}" data-month="{{date.mon}}" data-day="{{mday}}"
+                                    data-courseid="{{courseid}}" data-categoryid="{{categoryid}}"
+                                    data-timestamp="{{timestamp}}">{{mday}}</a>
                             {{/hasevents}}
                             {{^hasevents}}
-                                <div data-region="day-content">
-                                    {{mday}}
-                                </div>
+                                <span aria-hidden="true">{{mday}}</span>
                             {{/hasevents}}
                         </div>
                     </td>
diff --git a/templates/rwthonline_event_icon.mustache b/templates/rwthonline_event_icon.mustache
deleted file mode 100644
index cdbd341edce6e07dd97359ca3246f66943645822..0000000000000000000000000000000000000000
--- a/templates/rwthonline_event_icon.mustache
+++ /dev/null
@@ -1,40 +0,0 @@
-{{!
-    This file is part of Moodle - http://moodle.org/
-
-    Moodle is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    Moodle is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-}}
-{{!
-    @template local_rwth_sd_sync/rwthonline_event_icon
-
-    RWTHonline event icon display.
-
-    The purpose of this template is to render the RWTHonline event icon.
-
-    Classes required for JS:
-    * none
-
-    Data attributes required for JS:
-    * none
-
-    Example context (json):
-    {
-    }
-}}
-<div class="rwthonline_event_icon_rendered" style="display: none;"></div> <!-- this is just so that we don't render the RWTHonline icon again if it's already been rendered -->
-{{#title}}
-{{#pix}} i/rwthonline, local_rwth_sd_sync, {{{title}}} {{/pix}}
-{{/title}}
-{{^title}}
-{{#pix}} i/rwthonline, local_rwth_sd_sync {{/pix}}
-{{/title}}
\ No newline at end of file
diff --git a/version.php b/version.php
index ba2c492ec882764909ee26f7eeee5d550f7969a4..5ad80efb9e899f660ddd039246cf1b57723d6a13 100644
--- a/version.php
+++ b/version.php
@@ -24,9 +24,9 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2022042500;
+$plugin->version   = 2022071300;
 $plugin->requires  = 2020061500; // Requires Moodle 3.9.0.
 $plugin->maturity = MATURITY_STABLE;
-$plugin->release = '2.6.0';
+$plugin->release = '2.6.1';
 
 $plugin->component = 'local_rwth_sd_sync';