diff --git a/calendar/amd/build/calendar.min.js b/calendar/amd/build/calendar.min.js
index b9d8d94a534..a21c4753d0f 100644
--- a/calendar/amd/build/calendar.min.js
+++ b/calendar/amd/build/calendar.min.js
@@ -1 +1 @@
-define(["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p={ROOT:"[data-region='calendar']",DAY:"[data-region='day']",EVENT_ITEM:"[data-region='event-item']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']",DAY_CONTENT:"[data-region='day-content']",LOADING_ICON:".loading-icon",VIEW_DAY_LINK:"[data-action='view-day-link']",CALENDAR_MONTH_WRAPPER:".calendarwrapper",TODAY:".today"},q=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},r=function(a){k.getEventById(a).then(function(b){if(!b.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+a);var c=b.event;return q(c.eventtype).then(function(a){return c.eventtype=a,c})}).then(function(a){var b={title:a.name,type:j.TYPE,body:d.render("core_calendar/event_summary_body",a),templateContext:{canedit:a.canedit,candelete:a.candelete,isactionevent:a.isactionevent,url:a.url}};return h.create(b)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},s=function(b,c,f,g){var h=null,i=g.attr("data-day-timestamp");f&&(h=f.attr("data-day-timestamp")),f&&h==i||d.render("core/loading",{}).then(function(a,b){g.find(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(f,a,b))}).then(function(){return k.updateEventStartDay(c,i)}).then(function(){a("body").trigger(l.eventMoved,[c,f,g])}).always(function(){var a=g.find(p.LOADING_ICON);if(g.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(p.LOADING_ICON);f.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},t=function(b,c){var d=a("body");d.on(l.created,function(){m.reloadCurrentMonth(b)}),d.on(l.deleted,function(){m.reloadCurrentMonth(b)}),d.on(l.updated,function(){m.reloadCurrentMonth(b)}),d.on(l.editActionEvent,function(a,b){window.location.assign(b)}),d.on(l.moveEvent,s),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(c,d){var e=b.find(o.wrapper);a.setEventId(d),a.setContextId(e.data("contextId")),a.show()})}).fail(e.exception)},u=function(b){b.on("click",p.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null,e=c.closest(p.EVENT_LINK);d=e.length?e.data("eventId"):c.find(p.EVENT_LINK).data("eventId"),r(d)}),b.on("change",o.elements.courseSelector,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d,null).then(function(){return b.find(o.elements.courseSelector).val(d)}).fail(e.exception)});var c=n.registerEventFormModal(b);t(b,c),b.on("click",p.DAY,function(b){var d=a(b.target);if(!d.is(p.VIEW_DAY_LINK)){var f=a(this).attr("data-new-event-timestamp");c.then(function(a){var b=d.closest(o.wrapper);a.setCourseId(b.data("courseid"));var c=b.data("categoryid");"undefined"!=typeof c&&a.setCategoryId(c),a.setContextId(b.data("contextId")),a.setStartTime(f),a.show()}).fail(e.exception),b.preventDefault()}})};return{init:function(b){b=a(b),m.init(b),u(b)}}});
\ No newline at end of file
+define(["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p={ROOT:"[data-region='calendar']",DAY:"[data-region='day']",EVENT_ITEM:"[data-region='event-item']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']",DAY_CONTENT:"[data-region='day-content']",LOADING_ICON:".loading-icon",VIEW_DAY_LINK:"[data-action='view-day-link']",CALENDAR_MONTH_WRAPPER:".calendarwrapper",TODAY:".today"},q=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},r=function(a){switch(a){case"user":return"calendar_event_user";case"site":return"calendar_event_site";case"group":return"calendar_event_group";case"category":return"calendar_event_category";case"course":return"calendar_event_course";default:return"calendar_event_course"}},s=function(a){var b="";k.getEventById(a).then(function(c){if(!c.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+a);var d=c.event;return b=r(d.eventtype),q(d.eventtype).then(function(a){return d.eventtype=a,d})}).then(function(a){var c={title:a.name,type:j.TYPE,body:d.render("core_calendar/event_summary_body",a),templateContext:{canedit:a.canedit,candelete:a.candelete,headerclasses:b,isactionevent:a.isactionevent,url:a.url}};return h.create(c)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},t=function(b,c,f,g){var h=null,i=g.attr("data-day-timestamp");f&&(h=f.attr("data-day-timestamp")),f&&h==i||d.render("core/loading",{}).then(function(a,b){g.find(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(f,a,b))}).then(function(){return k.updateEventStartDay(c,i)}).then(function(){a("body").trigger(l.eventMoved,[c,f,g])}).always(function(){var a=g.find(p.LOADING_ICON);if(g.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(p.LOADING_ICON);f.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},u=function(b,c){var d=a("body");d.on(l.created,function(){m.reloadCurrentMonth(b)}),d.on(l.deleted,function(){m.reloadCurrentMonth(b)}),d.on(l.updated,function(){m.reloadCurrentMonth(b)}),d.on(l.editActionEvent,function(a,b){window.location.assign(b)}),d.on(l.moveEvent,t),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(c,d){var e=b.find(o.wrapper);a.setEventId(d),a.setContextId(e.data("contextId")),a.show()})}).fail(e.exception)},v=function(b){b.on("click",p.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null,e=c.closest(p.EVENT_LINK);d=e.length?e.data("eventId"):c.find(p.EVENT_LINK).data("eventId"),s(d)}),b.on("change",o.elements.courseSelector,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d,null).then(function(){return b.find(o.elements.courseSelector).val(d)}).fail(e.exception)});var c=n.registerEventFormModal(b);u(b,c),b.on("click",p.DAY,function(b){var d=a(b.target);if(!d.is(p.VIEW_DAY_LINK)){var f=a(this).attr("data-new-event-timestamp");c.then(function(a){var b=d.closest(o.wrapper);a.setCourseId(b.data("courseid"));var c=b.data("categoryid");"undefined"!=typeof c&&a.setCategoryId(c),a.setContextId(b.data("contextId")),a.setStartTime(f),a.show()}).fail(e.exception),b.preventDefault()}})};return{init:function(b){b=a(b),m.init(b),v(b)}}});
\ No newline at end of file
diff --git a/calendar/amd/src/calendar.js b/calendar/amd/src/calendar.js
index 67fee60831f..4b25c1a5126 100644
--- a/calendar/amd/src/calendar.js
+++ b/calendar/amd/src/calendar.js
@@ -86,18 +86,44 @@ define([
});
};
+ /**
+ * Get the CSS class to apply for the given event type.
+ *
+ * @param {String} eventType The calendar event type
+ * @return {String}
+ */
+ var getEventTypeClassFromType = function(eventType) {
+ switch (eventType) {
+ case 'user':
+ return 'calendar_event_user';
+ case 'site':
+ return 'calendar_event_site';
+ case 'group':
+ return 'calendar_event_group';
+ case 'category':
+ return 'calendar_event_category';
+ case 'course':
+ return 'calendar_event_course';
+ default:
+ return 'calendar_event_course';
+ }
+ };
+
/**
* Render the event summary modal.
*
* @param {Number} eventId The calendar event id.
*/
var renderEventSummaryModal = function(eventId) {
+ var typeClass = '';
+
// Calendar repository promise.
CalendarRepository.getEventById(eventId).then(function(getEventResponse) {
if (!getEventResponse.event) {
throw new Error('Error encountered while trying to fetch calendar event with ID: ' + eventId);
}
var eventData = getEventResponse.event;
+ typeClass = getEventTypeClassFromType(eventData.eventtype);
return getEventType(eventData.eventtype).then(function(eventType) {
eventData.eventtype = eventType;
@@ -112,6 +138,7 @@ define([
templateContext: {
canedit: eventData.canedit,
candelete: eventData.candelete,
+ headerclasses: typeClass,
isactionevent: eventData.isactionevent,
url: eventData.url
}
diff --git a/calendar/templates/event_summary_body.mustache b/calendar/templates/event_summary_body.mustache
index 2a672334454..0770cc501a3 100644
--- a/calendar/templates/event_summary_body.mustache
+++ b/calendar/templates/event_summary_body.mustache
@@ -37,24 +37,57 @@
}} data-action-event="{{isactionevent}}"{{!
}} data-edit-url="{{editurl}}"{{!
}}>
-
{{#str}} when, core_calendar {{/str}}
- {{#userdate}} {{timestart}}, {{#str}} strftimerecentfull {{/str}} {{/userdate}}
-
- {{#description}}
- {{#str}} description {{/str}}
- {{{description}}}
- {{/description}}
- {{#str}} eventtype, core_calendar {{/str}}
- {{eventtype}}
- {{#iscategoryevent}}
- {{{category.nestedname}}}
- {{/iscategoryevent}}
- {{#iscourseevent}}
-
- {{/iscourseevent}}
- {{> core_calendar/event_subscription}}
- {{#groupname}}
-
- {{{groupname}}}
- {{/groupname}}
+
+
+
{{#pix}} i/calendareventtime, core, {{#str}} when, core_calendar {{/str}} {{/pix}}
+
{{#userdate}} {{timestart}}, {{#str}} strftimerecentfull {{/str}} {{/userdate}}
+
+
+
{{#pix}} i/calendar, core, {{#str}} eventtype, core_calendar {{/str}} {{/pix}}
+
{{eventtype}}
+
+ {{#description}}
+
+
{{#pix}} i/calendareventdescription, core, {{#str}} description {{/str}} {{/pix}}
+
{{{.}}}
+
+ {{/description}}
+ {{#iscategoryevent}}
+
+
{{#pix}} i/categoryevent, core, {{#str}} category {{/str}} {{/pix}}
+
{{{category.nestedname}}}
+
+ {{/iscategoryevent}}
+ {{#iscourseevent}}
+
+
{{#pix}} i/courseevent, core, {{#str}} course {{/str}} {{/pix}}
+
+
+ {{/iscourseevent}}
+ {{#groupname}}
+
+
{{#pix}} i/courseevent, core, {{#str}} course {{/str}} {{/pix}}
+
+
+
+
{{#pix}} i/groupevent, core, {{#str}} group {{/str}} {{/pix}}
+
{{{groupname}}}
+
+ {{/groupname}}
+ {{#subscription}}
+ {{#displayeventsource}}
+
+
{{#pix}} i/rss, core, {{#str}} eventsource, core_calendar {{/str}} {{/pix}}
+
+
+ {{/displayeventsource}}
+ {{/subscription}}
+
diff --git a/lang/en/calendar.php b/lang/en/calendar.php
index 01dcd4fa605..206ebb217f6 100644
--- a/lang/en/calendar.php
+++ b/lang/en/calendar.php
@@ -108,6 +108,7 @@ $string['eventrepeat'] = 'Repeats';
$string['eventsall'] = 'All events';
$string['eventsdeleted'] = 'Events deleted';
$string['eventsimported'] = 'Events imported: {$a}';
+$string['eventsource'] = 'Event source';
$string['eventsupdated'] = 'Events updated: {$a}';
$string['eventsfor'] = '{$a} events';
$string['eventskey'] = 'Events key';
diff --git a/lib/amd/build/modal.min.js b/lib/amd/build/modal.min.js
index a280a27d941..ab2020f8997 100644
--- a/lib/amd/build/modal.min.js
+++ b/lib/amd/build/modal.min.js
@@ -1 +1 @@
-define(["jquery","core/templates","core/notification","core/key_codes","core/custom_interaction_events","core/modal_backdrop","core/event","core/modal_events"],function(a,b,c,d,e,f,g,h){var i,j={CONTAINER:'[data-region="modal-container"]',MODAL:'[data-region="modal"]',HEADER:'[data-region="header"]',TITLE:'[data-region="title"]',BODY:'[data-region="body"]',FOOTER:'[data-region="footer"]',HIDE:'[data-action="hide"]',DIALOG:"[role=dialog]",MENU_BAR:"[role=menubar]",HAS_Z_INDEX:".moodle-has-zindex",CAN_RECEIVE_FOCUS:'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]'},k={LOADING:"core/loading",BACKDROP:"core/modal_backdrop"},l=0,m=function(b){this.root=a(b),this.modal=this.root.find(j.MODAL),this.header=this.modal.find(j.HEADER),this.title=this.header.find(j.TITLE),this.body=this.modal.find(j.BODY),this.footer=this.modal.find(j.FOOTER),this.hiddenSiblings=[],this.isAttached=!1,this.bodyJS=null,this.footerJS=null,this.modalCount=l++,this.root.is(j.CONTAINER)||c.exception({message:"Element is not a modal container"}),this.modal.length||c.exception({message:"Container does not contain a modal"}),this.header.length||c.exception({message:"Modal is missing a header region"}),this.title.length||c.exception({message:"Modal header is missing a title region"}),this.body.length||c.exception({message:"Modal is missing a body region"}),this.footer.length||c.exception({message:"Modal is missing a footer region"}),this.registerEventListeners()};return m.prototype.attachToDOM=function(){this.isAttached||(a("body").append(this.root),this.bodyJS&&(b.runTemplateJS(this.bodyJS),this.bodyJS=null),this.footerJS&&(b.runTemplateJS(this.footerJS),this.footerJS=null),this.isAttached=!0)},m.prototype.countOtherVisibleModals=function(){var b=0;return a("body").find(j.CONTAINER).each(function(c,d){d=a(d),!this.root.is(d)&&d.hasClass("show")&&b++}.bind(this)),b},m.prototype.getBackdrop=function(){return i||(i=b.render(k.BACKDROP,{}).then(function(b){var c=a(b);return new f(c)}).fail(c.exception)),i},m.prototype.getRoot=function(){return this.root},m.prototype.getModal=function(){return this.modal},m.prototype.getTitle=function(){return this.title},m.prototype.getBody=function(){return this.body},m.prototype.getFooter=function(){return this.footer},m.prototype.getModalCount=function(){return this.modalCount},m.prototype.setTitle=function(a){var b=this.getTitle();this.asyncSet(a,b.html.bind(b))},m.prototype.setBody=function(d){var e=this.getBody();if("string"==typeof d)e.html(d),g.notifyFilterContentUpdated(e),this.getRoot().trigger(h.bodyRendered,this);else{var f="amd-modal-js-pending-id-"+this.getModalCount();M.util.js_pending(f);var i=null;e.css("overflow","hidden"),"pending"==d.state()?(e.animate({height:"100px"},150),e.html(""),i=b.render(k.LOADING,{}).then(function(b){var c=a(b).hide();return e.html(c),c.fadeIn(150),a.when(c.promise(),d)}).then(function(a){return a.fadeOut(100).promise()}).then(function(){return d})):i=d,i.then(function(a,c){var d=null;if(this.isVisible()){e.css("opacity",0);var f=e.innerHeight();e.html(a),e.css("height","");var i=e.innerHeight();e.css("height",f+"px"),d=e.animate({height:i+"px",opacity:1},{duration:150,queue:!1}).promise()}else e.html(a);return c&&(this.isAttached?b.runTemplateJS(c):this.bodyJS=c),g.notifyFilterContentUpdated(e),this.getRoot().trigger(h.bodyRendered,this),d}.bind(this)).fail(c.exception).always(function(){e.css("height",""),e.css("overflow",""),e.css("opacity",""),M.util.js_complete(f)}).fail(c.exception)}},m.prototype.setFooter=function(a){var c=this.getFooter();"string"==typeof a?c.html(a):b.render(k.LOADING,{}).done(function(d){c.html(d),a.done(function(a,d){c.html(a),d&&(this.isAttached?b.runTemplateJS(d):this.footerJS=d)}.bind(this))}.bind(this))},m.prototype.setLarge=function(){this.isLarge()||this.getModal().addClass("modal-lg")},m.prototype.isLarge=function(){return this.getModal().hasClass("modal-lg")},m.prototype.setSmall=function(){this.isSmall()||this.getModal().removeClass("modal-lg")},m.prototype.isSmall=function(){return!this.getModal().hasClass("modal-lg")},m.prototype.calculateZIndex=function(){var b=a(j.DIALOG+", "+j.MENU_BAR+", "+j.HAS_Z_INDEX),c=parseInt(this.root.css("z-index"));return b.each(function(b,d){d=a(d);var e=d.css("z-index")?parseInt(d.css("z-index")):0;e>c&&(c=e)}),c},m.prototype.isVisible=function(){return this.root.hasClass("show")},m.prototype.hasFocus=function(){var b=a(document.activeElement);return this.root.is(b)||this.root.has(b).length},m.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")},m.prototype.show=function(){this.isVisible()||(this.isAttached||this.attachToDOM(),this.getBackdrop().done(function(b){var c=this.calculateZIndex(),d=c+2,e=d-1;this.root.css("z-index",d),b.setZIndex(e),b.show(),this.root.removeClass("hide").addClass("show"),this.accessibilityShow(),this.getTitle().focus(),a("body").addClass("modal-open"),this.root.trigger(h.shown,this)}.bind(this)))},m.prototype.hide=function(){this.isVisible()&&this.getBackdrop().done(function(b){this.countOtherVisibleModals()||(b.hide(),a("body").removeClass("modal-open"));var c=parseInt(this.root.css("z-index"));this.root.css("z-index",""),b.setZIndex(c-3),this.accessibilityHide(),this.hasTransitions()?this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",function(){this.getRoot().removeClass("show").addClass("hide")}.bind(this)):this.getRoot().removeClass("show").addClass("hide"),this.root.trigger(h.hidden,this)}.bind(this))},m.prototype.destroy=function(){this.root.remove(),this.root.trigger(h.destroyed,this)},m.prototype.accessibilityShow=function(){a("body").children().each(function(b,c){if(!this.root.is(c)){c=a(c);var d=c.attr("aria-hidden");"true"!==d&&(c.data("previous-aria-hidden",d),this.hiddenSiblings.push(c),c.attr("aria-hidden","true"))}}.bind(this)),this.root.attr("aria-hidden","false")},m.prototype.accessibilityHide=function(){this.root.attr("aria-hidden","true"),a.each(this.hiddenSiblings,function(b,c){c=a(c);var d=c.data("previous-aria-hidden");"undefined"==typeof d?c.removeAttr("aria-hidden"):c.attr("aria-hidden",d)}),this.hiddenSiblings=[]},m.prototype.handleTabLock=function(b){if(this.hasFocus()){var c=a(document.activeElement),d=this.modal.find(j.CAN_RECEIVE_FOCUS),e=d.first(),f=d.last();c.is(e)&&b.shiftKey?(f.focus(),b.preventDefault()):c.is(f)&&!b.shiftKey&&(e.focus(),b.preventDefault())}},m.prototype.registerEventListeners=function(){this.getRoot().on("keydown",function(a){this.isVisible()&&(a.keyCode==d.tab?this.handleTabLock(a):a.keyCode==d.escape&&this.hide())}.bind(this)),e.define(this.getModal(),[e.events.activate]),this.getModal().on(e.events.activate,j.HIDE,function(a,b){this.hide(),b.originalEvent.preventDefault()}.bind(this))},m.prototype.asyncSet=function(b,d){var e=b;return"object"==typeof b&&b.hasOwnProperty("then")||(e=a.Deferred(),e.resolve(b)),e.then(function(a){d(a)}).fail(c.exception),e},m});
\ No newline at end of file
+define(["jquery","core/templates","core/notification","core/key_codes","core/custom_interaction_events","core/modal_backdrop","core/event","core/modal_events"],function(a,b,c,d,e,f,g,h){var i,j={CONTAINER:'[data-region="modal-container"]',MODAL:'[data-region="modal"]',HEADER:'[data-region="header"]',TITLE:'[data-region="title"]',BODY:'[data-region="body"]',FOOTER:'[data-region="footer"]',HIDE:'[data-action="hide"]',DIALOG:"[role=dialog]",MENU_BAR:"[role=menubar]",HAS_Z_INDEX:".moodle-has-zindex",CAN_RECEIVE_FOCUS:'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]'},k={LOADING:"core/loading",BACKDROP:"core/modal_backdrop"},l=0,m=function(b){this.root=a(b),this.modal=this.root.find(j.MODAL),this.header=this.modal.find(j.HEADER),this.title=this.header.find(j.TITLE),this.body=this.modal.find(j.BODY),this.footer=this.modal.find(j.FOOTER),this.hiddenSiblings=[],this.isAttached=!1,this.bodyJS=null,this.footerJS=null,this.modalCount=l++,this.root.is(j.CONTAINER)||c.exception({message:"Element is not a modal container"}),this.modal.length||c.exception({message:"Container does not contain a modal"}),this.header.length||c.exception({message:"Modal is missing a header region"}),this.title.length||c.exception({message:"Modal header is missing a title region"}),this.body.length||c.exception({message:"Modal is missing a body region"}),this.footer.length||c.exception({message:"Modal is missing a footer region"}),this.registerEventListeners()};return m.prototype.attachToDOM=function(){this.isAttached||(a("body").append(this.root),this.bodyJS&&(b.runTemplateJS(this.bodyJS),this.bodyJS=null),this.footerJS&&(b.runTemplateJS(this.footerJS),this.footerJS=null),this.isAttached=!0)},m.prototype.countOtherVisibleModals=function(){var b=0;return a("body").find(j.CONTAINER).each(function(c,d){d=a(d),!this.root.is(d)&&d.hasClass("show")&&b++}.bind(this)),b},m.prototype.getBackdrop=function(){return i||(i=b.render(k.BACKDROP,{}).then(function(b){var c=a(b);return new f(c)}).fail(c.exception)),i},m.prototype.getRoot=function(){return this.root},m.prototype.getModal=function(){return this.modal},m.prototype.getTitle=function(){return this.title},m.prototype.getBody=function(){return this.body},m.prototype.getFooter=function(){return this.footer},m.prototype.getModalCount=function(){return this.modalCount},m.prototype.setTitle=function(a){var b=this.getTitle();this.asyncSet(a,b.html.bind(b))},m.prototype.setBody=function(d){var e=this.getBody();if("string"==typeof d)e.html(d),g.notifyFilterContentUpdated(e),this.getRoot().trigger(h.bodyRendered,this);else{var f="amd-modal-js-pending-id-"+this.getModalCount();M.util.js_pending(f);var i=null;e.css("overflow","hidden"),"pending"==d.state()?(e.animate({height:"100px"},150),e.html(""),i=b.render(k.LOADING,{}).then(function(b){var c=a(b).hide();return e.html(c),c.fadeIn(150),a.when(c.promise(),d)}).then(function(a){return a.fadeOut(100).promise()}).then(function(){return d})):i=d,i.then(function(a,c){var d=null;if(this.isVisible()){e.css("opacity",0);var f=e.innerHeight();e.html(a),e.css("height","");var i=e.innerHeight();e.css("height",f+"px"),d=e.animate({height:i+"px",opacity:1},{duration:150,queue:!1}).promise()}else e.html(a);return c&&(this.isAttached?b.runTemplateJS(c):this.bodyJS=c),g.notifyFilterContentUpdated(e),this.getRoot().trigger(h.bodyRendered,this),d}.bind(this)).fail(c.exception).always(function(){e.css("height",""),e.css("overflow",""),e.css("opacity",""),M.util.js_complete(f)}).fail(c.exception)}},m.prototype.setFooter=function(a){this.showFooter();var c=this.getFooter();"string"==typeof a?c.html(a):b.render(k.LOADING,{}).done(function(d){c.html(d),a.done(function(a,d){c.html(a),d&&(this.isAttached?b.runTemplateJS(d):this.footerJS=d)}.bind(this))}.bind(this))},m.prototype.hasFooterContent=function(){return!!this.getFooter().children().length},m.prototype.hideFooter=function(){this.getFooter().addClass("hidden")},m.prototype.showFooter=function(){this.getFooter().removeClass("hidden")},m.prototype.setLarge=function(){this.isLarge()||this.getModal().addClass("modal-lg")},m.prototype.isLarge=function(){return this.getModal().hasClass("modal-lg")},m.prototype.setSmall=function(){this.isSmall()||this.getModal().removeClass("modal-lg")},m.prototype.isSmall=function(){return!this.getModal().hasClass("modal-lg")},m.prototype.calculateZIndex=function(){var b=a(j.DIALOG+", "+j.MENU_BAR+", "+j.HAS_Z_INDEX),c=parseInt(this.root.css("z-index"));return b.each(function(b,d){d=a(d);var e=d.css("z-index")?parseInt(d.css("z-index")):0;e>c&&(c=e)}),c},m.prototype.isVisible=function(){return this.root.hasClass("show")},m.prototype.hasFocus=function(){var b=a(document.activeElement);return this.root.is(b)||this.root.has(b).length},m.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")},m.prototype.show=function(){this.isVisible()||(this.hasFooterContent()?this.showFooter():this.hideFooter(),this.isAttached||this.attachToDOM(),this.getBackdrop().done(function(b){var c=this.calculateZIndex(),d=c+2,e=d-1;this.root.css("z-index",d),b.setZIndex(e),b.show(),this.root.removeClass("hide").addClass("show"),this.accessibilityShow(),this.getTitle().focus(),a("body").addClass("modal-open"),this.root.trigger(h.shown,this)}.bind(this)))},m.prototype.hide=function(){this.isVisible()&&this.getBackdrop().done(function(b){this.countOtherVisibleModals()||(b.hide(),a("body").removeClass("modal-open"));var c=parseInt(this.root.css("z-index"));this.root.css("z-index",""),b.setZIndex(c-3),this.accessibilityHide(),this.hasTransitions()?this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",function(){this.getRoot().removeClass("show").addClass("hide")}.bind(this)):this.getRoot().removeClass("show").addClass("hide"),this.root.trigger(h.hidden,this)}.bind(this))},m.prototype.destroy=function(){this.root.remove(),this.root.trigger(h.destroyed,this)},m.prototype.accessibilityShow=function(){a("body").children().each(function(b,c){if(!this.root.is(c)){c=a(c);var d=c.attr("aria-hidden");"true"!==d&&(c.data("previous-aria-hidden",d),this.hiddenSiblings.push(c),c.attr("aria-hidden","true"))}}.bind(this)),this.root.attr("aria-hidden","false")},m.prototype.accessibilityHide=function(){this.root.attr("aria-hidden","true"),a.each(this.hiddenSiblings,function(b,c){c=a(c);var d=c.data("previous-aria-hidden");"undefined"==typeof d?c.removeAttr("aria-hidden"):c.attr("aria-hidden",d)}),this.hiddenSiblings=[]},m.prototype.handleTabLock=function(b){if(this.hasFocus()){var c=a(document.activeElement),d=this.modal.find(j.CAN_RECEIVE_FOCUS),e=d.first(),f=d.last();c.is(e)&&b.shiftKey?(f.focus(),b.preventDefault()):c.is(f)&&!b.shiftKey&&(e.focus(),b.preventDefault())}},m.prototype.registerEventListeners=function(){this.getRoot().on("keydown",function(a){this.isVisible()&&(a.keyCode==d.tab?this.handleTabLock(a):a.keyCode==d.escape&&this.hide())}.bind(this)),e.define(this.getModal(),[e.events.activate]),this.getModal().on(e.events.activate,j.HIDE,function(a,b){this.hide(),b.originalEvent.preventDefault()}.bind(this))},m.prototype.asyncSet=function(b,d){var e=b;return"object"==typeof b&&b.hasOwnProperty("then")||(e=a.Deferred(),e.resolve(b)),e.then(function(a){d(a)}).fail(c.exception),e},m});
\ No newline at end of file
diff --git a/lib/amd/src/modal.js b/lib/amd/src/modal.js
index 3f368b9e473..302cd8dc70d 100644
--- a/lib/amd/src/modal.js
+++ b/lib/amd/src/modal.js
@@ -358,7 +358,8 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
};
/**
- * Set the modal footer element.
+ * Set the modal footer element. The footer element is made visible, if it
+ * isn't already.
*
* This method is overloaded to take either a string
* value for the body or a jQuery promise that is resolved with HTML and Javascript
@@ -368,6 +369,9 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
* @param {(string|object)} value The footer string or jQuery promise
*/
Modal.prototype.setFooter = function(value) {
+ // Make sure the footer is visible.
+ this.showFooter();
+
var footer = this.getFooter();
if (typeof value === 'string') {
@@ -396,6 +400,34 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
}
};
+ /**
+ * Check if the footer has any content in it.
+ *
+ * @method hasFooterContent
+ * @return {bool}
+ */
+ Modal.prototype.hasFooterContent = function() {
+ return this.getFooter().children().length ? true : false;
+ };
+
+ /**
+ * Hide the footer element.
+ *
+ * @method hideFooter
+ */
+ Modal.prototype.hideFooter = function() {
+ this.getFooter().addClass('hidden');
+ };
+
+ /**
+ * Show the footer element.
+ *
+ * @method showFooter
+ */
+ Modal.prototype.showFooter = function() {
+ this.getFooter().removeClass('hidden');
+ };
+
/**
* Mark the modal as a large modal.
*
@@ -508,6 +540,12 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
return;
}
+ if (this.hasFooterContent()) {
+ this.showFooter();
+ } else {
+ this.hideFooter();
+ }
+
if (!this.isAttached) {
this.attachToDOM();
}
diff --git a/lib/classes/output/icon_system_fontawesome.php b/lib/classes/output/icon_system_fontawesome.php
index 055857a20cc..d7e858a42b1 100644
--- a/lib/classes/output/icon_system_fontawesome.php
+++ b/lib/classes/output/icon_system_fontawesome.php
@@ -195,6 +195,8 @@ class icon_system_fontawesome extends icon_system_font {
'core:i/badge' => 'fa-shield',
'core:i/calc' => 'fa-calculator',
'core:i/calendar' => 'fa-calendar',
+ 'core:i/calendareventdescription' => 'fa-align-left',
+ 'core:i/calendareventtime' => 'fa-clock-o',
'core:i/caution' => 'fa-exclamation text-warning',
'core:i/checked' => 'fa-check',
'core:i/checkpermissions' => 'fa-unlock-alt',
diff --git a/lib/templates/modal.mustache b/lib/templates/modal.mustache
index d8c4b70dafc..9436cbb0bbf 100644
--- a/lib/templates/modal.mustache
+++ b/lib/templates/modal.mustache
@@ -45,7 +45,7 @@
data-region="modal"
aria-labelledby="{{uniqid}}-modal-title"
role="document">
-