diff --git a/lib/amd/build/modal.min.js b/lib/amd/build/modal.min.js
index f4c546e4444..681584bc0ef 100644
--- a/lib/amd/build/modal.min.js
+++ b/lib/amd/build/modal.min.js
@@ -1,3 +1,3 @@
-define("core/modal",["exports","jquery","core/templates","core/notification","core/key_codes","core/modal_backdrop","core/modal_events","core/modal_registry","core/pending","core/custom_interaction_events","core_filters/events","core/local/aria/focuslock","core/aria","core/fullscreen"],(function(_exports,_jquery,Templates,Notification,KeyCodes,_modal_backdrop,_modal_events,ModalRegistry,_pending,CustomEvents,FilterEvents,FocusLock,Aria,Fullscreen){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),Templates=_interopRequireWildcard(Templates),Notification=_interopRequireWildcard(Notification),KeyCodes=_interopRequireWildcard(KeyCodes),_modal_backdrop=_interopRequireDefault(_modal_backdrop),_modal_events=_interopRequireDefault(_modal_events),ModalRegistry=_interopRequireWildcard(ModalRegistry),_pending=_interopRequireDefault(_pending),CustomEvents=_interopRequireWildcard(CustomEvents),FilterEvents=_interopRequireWildcard(FilterEvents),FocusLock=_interopRequireWildcard(FocusLock),Aria=_interopRequireWildcard(Aria),Fullscreen=_interopRequireWildcard(Fullscreen);const SELECTORS_CONTAINER='[data-region="modal-container"]',SELECTORS_MODAL='[data-region="modal"]',SELECTORS_HEADER='[data-region="header"]',SELECTORS_TITLE='[data-region="title"]',SELECTORS_BODY='[data-region="body"]',SELECTORS_FOOTER='[data-region="footer"]',SELECTORS_HIDE='[data-action="hide"]',SELECTORS_DIALOG="[role=dialog]",SELECTORS_FORM="form",SELECTORS_MENU_BAR="[role=menubar]",SELECTORS_HAS_Z_INDEX=".moodle-has-zindex",TEMPLATES_LOADING="core/loading",TEMPLATES_BACKDROP="core/modal_backdrop";class Modal{constructor(root){this.root=(0,_jquery.default)(root),this.modal=this.root.find(SELECTORS_MODAL),this.header=this.modal.find(SELECTORS_HEADER),this.headerPromise=_jquery.default.Deferred(),this.title=this.header.find(SELECTORS_TITLE),this.titlePromise=_jquery.default.Deferred(),this.body=this.modal.find(SELECTORS_BODY),this.bodyPromise=_jquery.default.Deferred(),this.footer=this.modal.find(SELECTORS_FOOTER),this.footerPromise=_jquery.default.Deferred(),this.hiddenSiblings=[],this.isAttached=!1,this.bodyJS=null,this.footerJS=null,this.modalCount=this.modalCounter++,this.attachmentPoint=document.createElement("div"),document.body.append(this.attachmentPoint),this.focusOnClose=null,this.root.is(SELECTORS_CONTAINER)||Notification.exception({message:"Element is not a modal container"}),this.modal.length||Notification.exception({message:"Container does not contain a modal"}),this.header.length||Notification.exception({message:"Modal is missing a header region"}),this.title.length||Notification.exception({message:"Modal header is missing a title region"}),this.body.length||Notification.exception({message:"Modal is missing a body region"}),this.footer.length||Notification.exception({message:"Modal is missing a footer region"}),this.registerEventListeners()}static registerModalType(){if(!this.TYPE)throw new Error("Unknown modal type",this);if(!this.TEMPLATE)throw new Error("Unknown modal template",this);ModalRegistry.register(this.TYPE,this,this.TEMPLATE)}attachToDOM(){this.getAttachmentPoint().append(this.root),this.isAttached||(FocusLock.trapFocus(this.root[0]),this.bodyJS&&(Templates.runTemplateJS(this.bodyJS),this.bodyJS=null),this.footerJS&&(Templates.runTemplateJS(this.footerJS),this.footerJS=null),this.isAttached=!0)}countOtherVisibleModals(){let count=0;return(0,_jquery.default)("body").find(SELECTORS_CONTAINER).each(((index,element)=>{element=(0,_jquery.default)(element),!this.root.is(element)&&element.hasClass("show")&&count++})),count}getBackdrop(){return Modal.backdropPromise||(Modal.backdropPromise=Templates.render(TEMPLATES_BACKDROP,{}).then((html=>new _modal_backdrop.default((0,_jquery.default)(html)))).catch(Notification.exception)),Modal.backdropPromise}getRoot(){return this.root}getModal(){return this.modal}getTitle(){return this.title}getBody(){return this.body}getFooter(){return this.footer}getTitlePromise(){return this.titlePromise}getBodyPromise(){return this.bodyPromise}getFooterPromise(){return this.footerPromise}getModalCount(){return this.modalCount}setTitle(value){const title=this.getTitle();this.titlePromise=_jquery.default.Deferred(),this.asyncSet(value,title.html.bind(title)).then((()=>{this.titlePromise.resolve(title)})).catch(Notification.exception)}setBody(value){this.bodyPromise=_jquery.default.Deferred();const body=this.getBody();if("string"==typeof value)body.html(value),FilterEvents.notifyFilterContentUpdated(body),this.getRoot().trigger(_modal_events.default.bodyRendered,this),this.bodyPromise.resolve(body);else{const modalPromise=new _pending.default("amd-modal-js-pending-id-".concat(this.getModalCount()));let contentPromise=null;if(body.css("overflow","hidden"),"pending"==(value=_jquery.default.when(value)).state()){let height=body.innerHeight();height<100&&(height=100),body.animate({height:"".concat(height,"px")},150),body.html(""),contentPromise=Templates.render(TEMPLATES_LOADING,{}).then((html=>{const loadingIcon=(0,_jquery.default)(html).hide();return body.html(loadingIcon),loadingIcon.fadeIn(150),_jquery.default.when(loadingIcon.promise(),value)})).then((loadingIcon=>loadingIcon.fadeOut(100).promise())).then((()=>value))}else contentPromise=value;contentPromise.then(((html,js)=>{let result=null;if(this.isVisible()){body.css("opacity",0);const currentHeight=body.innerHeight();body.html(html),body.css("height","");const newHeight=body.innerHeight();body.css("height","".concat(currentHeight,"px")),result=body.animate({height:"".concat(newHeight,"px"),opacity:1},{duration:150,queue:!1}).promise()}else body.html(html);return js&&(this.isAttached?Templates.runTemplateJS(js):this.bodyJS=js),result})).then((result=>(FilterEvents.notifyFilterContentUpdated(body),this.getRoot().trigger(_modal_events.default.bodyRendered,this),result))).then((()=>{this.bodyPromise.resolve(body)})).catch(Notification.exception).always((()=>{body.css("height",""),body.css("overflow",""),body.css("opacity",""),modalPromise.resolve()}))}}setBodyContent(promise){return promise.then((_ref=>{let{html:html,js:js}=_ref;return this.setBody(_jquery.default.when(html,js))})).catch((exception=>{throw this.hide(),exception}))}setFooter(value){this.showFooter(),this.footerPromise=_jquery.default.Deferred();const footer=this.getFooter();"string"==typeof value?(footer.html(value),this.footerPromise.resolve(footer)):Templates.render(TEMPLATES_LOADING,{}).then((html=>(footer.html(html),value))).then(((html,js)=>(footer.html(html),js&&(this.isAttached?Templates.runTemplateJS(js):this.footerJS=js),footer))).then((footer=>{this.footerPromise.resolve(footer)})).catch(Notification.exception)}hasFooterContent(){return!!this.getFooter().children().length}hideFooter(){this.getFooter().addClass("hidden")}showFooter(){this.getFooter().removeClass("hidden")}setLarge(){this.isLarge()||this.getModal().addClass("modal-lg")}setVerticallyCentered(){this.isVerticallyCentered()||this.getModal().addClass("modal-dialog-centered")}isLarge(){return this.getModal().hasClass("modal-lg")}isVerticallyCentered(){return this.getModal().hasClass("modal-dialog-centered")}setSmall(){this.isSmall()||this.getModal().removeClass("modal-lg")}isSmall(){return!this.getModal().hasClass("modal-lg")}setScrollable(value){value?this.getModal()[0].classList.add("modal-dialog-scrollable"):this.getModal()[0].classList.remove("modal-dialog-scrollable")}calculateZIndex(){const items=(0,_jquery.default)("".concat(SELECTORS_DIALOG,", ").concat(SELECTORS_MENU_BAR,", ").concat(SELECTORS_HAS_Z_INDEX));let zIndex=parseInt(this.root.css("z-index"));return items.each(((index,item)=>{if(!(item=(0,_jquery.default)(item)).is(":visible"))return;const itemZIndex=item.css("z-index")?parseInt(item.css("z-index")):0;itemZIndex>zIndex&&(zIndex=itemZIndex)})),zIndex}isVisible(){return this.root.hasClass("show")}hasFocus(){const target=(0,_jquery.default)(document.activeElement);return this.root.is(target)||this.root.has(target).length}hasTransitions(){return this.getRoot().hasClass("fade")}getAttachmentPoint(){return(0,_jquery.default)(Fullscreen.getElement()||this.attachmentPoint)}show(){if(this.isVisible())return _jquery.default.Deferred().resolve();const pendingPromise=new _pending.default("core/modal:show");return this.hasFooterContent()?this.showFooter():this.hideFooter(),this.attachToDOM(),!this.focusOnClose&&document.activeElement&&(this.focusOnClose=document.activeElement),this.getBackdrop().then((backdrop=>{const newIndex=this.calculateZIndex()+2,newBackdropIndex=newIndex-1;this.root.css("z-index",newIndex),backdrop.setZIndex(newBackdropIndex),backdrop.show(),this.root.removeClass("hide").addClass("show"),this.accessibilityShow(),this.getModal().focus(),(0,_jquery.default)("body").addClass("modal-open"),this.root.trigger(_modal_events.default.shown,this)})).then(pendingPromise.resolve)}hideIfNotForm(){0==this.modal.find(SELECTORS_FORM).length&&this.hide()}hide(){this.getBackdrop().done((backdrop=>{FocusLock.untrapFocus(),this.countOtherVisibleModals()||(backdrop.hide(),(0,_jquery.default)("body").removeClass("modal-open"));const currentIndex=parseInt(this.root.css("z-index"));this.root.css("z-index",""),backdrop.setZIndex(currentIndex-3),this.accessibilityHide(),this.hasTransitions()?this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",(()=>{this.getRoot().removeClass("show").addClass("hide")})):this.getRoot().removeClass("show").addClass("hide"),(0,_jquery.default)(document.body).find(this.getRoot()).length&&(0,_jquery.default)(document.body).append(this.getRoot()),this.root.trigger(_modal_events.default.hidden,this)}))}destroy(){this.hide(),this.root.remove(),this.root.trigger(_modal_events.default.destroyed,this),this.attachmentPoint.remove()}accessibilityShow(){Aria.unhide(this.root.get()),Aria.hideSiblings(this.root.get()[0])}accessibilityHide(){Aria.unhideSiblings(this.root.get()[0]),Aria.hide(this.root.get())}registerEventListeners(){this.getRoot().on("keydown",(e=>{this.isVisible()&&e.keyCode==KeyCodes.escape&&(this.removeOnClose?this.destroy():this.hide())})),this.getRoot().click((e=>{if(!(0,_jquery.default)(e.target).closest(SELECTORS_MODAL).length&&(0,_jquery.default)(e.target).closest(SELECTORS_CONTAINER).length){const outsideClickEvent=_jquery.default.Event(_modal_events.default.outsideClick);this.getRoot().trigger(outsideClickEvent,this),outsideClickEvent.isDefaultPrevented()||this.hideIfNotForm()}})),CustomEvents.define(this.getModal(),[CustomEvents.events.activate]),this.getModal().on(CustomEvents.events.activate,SELECTORS_HIDE,((e,data)=>{this.removeOnClose?this.destroy():this.hide(),data.originalEvent.preventDefault()})),this.getRoot().on(_modal_events.default.hidden,(()=>{this.focusOnClose&&this.focusOnClose.focus()}))}registerCloseOnCancel(){this.getModal().on(CustomEvents.events.activate,this.getActionSelector("cancel"),((e,data)=>{const cancelEvent=_jquery.default.Event(_modal_events.default.cancel);this.getRoot().trigger(cancelEvent,this),cancelEvent.isDefaultPrevented()||(data.originalEvent.preventDefault(),this.removeOnClose?this.destroy():this.hide())}))}registerCloseOnSave(){this.getModal().on(CustomEvents.events.activate,this.getActionSelector("save"),((e,data)=>{const saveEvent=_jquery.default.Event(_modal_events.default.save);this.getRoot().trigger(saveEvent,this),saveEvent.isDefaultPrevented()||(data.originalEvent.preventDefault(),this.removeOnClose?this.destroy():this.hide())}))}registerCloseOnDelete(){this.getModal().on(CustomEvents.events.activate,this.getActionSelector("delete"),((e,data)=>{const deleteEvent=_jquery.default.Event(_modal_events.default.delete);this.getRoot().trigger(deleteEvent,this),deleteEvent.isDefaultPrevented()||(data.originalEvent.preventDefault(),this.removeOnClose?this.destroy():this.hide())}))}asyncSet(value,setFunction){return(value=>value instanceof Promise?_jquery.default.when(value):"object"==typeof value&&value.hasOwnProperty("then")?value:_jquery.default.Deferred().resolve(value))(value).then((content=>setFunction(content))).catch(Notification.exception)}setButtonText(action,value){const button=this.getFooter().find(this.getActionSelector(action));if(!button)throw new Error("Unable to find the '"+action+"' button");return this.asyncSet(value,button.text.bind(button))}getActionSelector(action){return"[data-action='"+action+"']"}setRemoveOnClose(remove){this.removeOnClose=remove}setReturnElement(element){this.focusOnClose=element}setButtonDisabled(action,disabled){const button=this.getFooter().find(this.getActionSelector(action));if(!button)throw new Error("Unable to find the '"+action+"' button");disabled?button.attr("disabled",""):button.removeAttr("disabled")}}return _exports.default=Modal,_defineProperty(Modal,"TEMPLATE","core/modal"),_defineProperty(Modal,"backdropPromise",null),_defineProperty(Modal,"modalCounter",0),_exports.default}));
+define("core/modal",["exports","jquery","core/templates","core/notification","core/key_codes","core/modal_backdrop","core/modal_events","core/modal_registry","core/pending","core/custom_interaction_events","core_filters/events","core/local/aria/focuslock","core/aria","core/fullscreen"],(function(_exports,_jquery,Templates,Notification,KeyCodes,_modal_backdrop,_modal_events,ModalRegistry,_pending,CustomEvents,FilterEvents,FocusLock,Aria,Fullscreen){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),Templates=_interopRequireWildcard(Templates),Notification=_interopRequireWildcard(Notification),KeyCodes=_interopRequireWildcard(KeyCodes),_modal_backdrop=_interopRequireDefault(_modal_backdrop),_modal_events=_interopRequireDefault(_modal_events),ModalRegistry=_interopRequireWildcard(ModalRegistry),_pending=_interopRequireDefault(_pending),CustomEvents=_interopRequireWildcard(CustomEvents),FilterEvents=_interopRequireWildcard(FilterEvents),FocusLock=_interopRequireWildcard(FocusLock),Aria=_interopRequireWildcard(Aria),Fullscreen=_interopRequireWildcard(Fullscreen);const SELECTORS_CONTAINER='[data-region="modal-container"]',SELECTORS_MODAL='[data-region="modal"]',SELECTORS_HEADER='[data-region="header"]',SELECTORS_TITLE='[data-region="title"]',SELECTORS_BODY='[data-region="body"]',SELECTORS_FOOTER='[data-region="footer"]',SELECTORS_HIDE='[data-action="hide"]',SELECTORS_DIALOG="[role=dialog]",SELECTORS_FORM="form",SELECTORS_MENU_BAR="[role=menubar]",SELECTORS_HAS_Z_INDEX=".moodle-has-zindex",TEMPLATES_LOADING="core/loading",TEMPLATES_BACKDROP="core/modal_backdrop";class Modal{constructor(root){this.root=(0,_jquery.default)(root),this.modal=this.root.find(SELECTORS_MODAL),this.header=this.modal.find(SELECTORS_HEADER),this.headerPromise=_jquery.default.Deferred(),this.title=this.header.find(SELECTORS_TITLE),this.titlePromise=_jquery.default.Deferred(),this.body=this.modal.find(SELECTORS_BODY),this.bodyPromise=_jquery.default.Deferred(),this.footer=this.modal.find(SELECTORS_FOOTER),this.footerPromise=_jquery.default.Deferred(),this.hiddenSiblings=[],this.isAttached=!1,this.bodyJS=null,this.footerJS=null,this.modalCount=Modal.modalCounter++,this.attachmentPoint=document.createElement("div"),document.body.append(this.attachmentPoint),this.focusOnClose=null,this.root.is(SELECTORS_CONTAINER)||Notification.exception({message:"Element is not a modal container"}),this.modal.length||Notification.exception({message:"Container does not contain a modal"}),this.header.length||Notification.exception({message:"Modal is missing a header region"}),this.title.length||Notification.exception({message:"Modal header is missing a title region"}),this.body.length||Notification.exception({message:"Modal is missing a body region"}),this.footer.length||Notification.exception({message:"Modal is missing a footer region"}),this.registerEventListeners()}static registerModalType(){if(!this.TYPE)throw new Error("Unknown modal type",this);if(!this.TEMPLATE)throw new Error("Unknown modal template",this);ModalRegistry.register(this.TYPE,this,this.TEMPLATE)}attachToDOM(){this.getAttachmentPoint().append(this.root),this.isAttached||(FocusLock.trapFocus(this.root[0]),this.bodyJS&&(Templates.runTemplateJS(this.bodyJS),this.bodyJS=null),this.footerJS&&(Templates.runTemplateJS(this.footerJS),this.footerJS=null),this.isAttached=!0)}countOtherVisibleModals(){let count=0;return(0,_jquery.default)("body").find(SELECTORS_CONTAINER).each(((index,element)=>{element=(0,_jquery.default)(element),!this.root.is(element)&&element.hasClass("show")&&count++})),count}getBackdrop(){return Modal.backdropPromise||(Modal.backdropPromise=Templates.render(TEMPLATES_BACKDROP,{}).then((html=>new _modal_backdrop.default((0,_jquery.default)(html)))).catch(Notification.exception)),Modal.backdropPromise}getRoot(){return this.root}getModal(){return this.modal}getTitle(){return this.title}getBody(){return this.body}getFooter(){return this.footer}getTitlePromise(){return this.titlePromise}getBodyPromise(){return this.bodyPromise}getFooterPromise(){return this.footerPromise}getModalCount(){return this.modalCount}setTitle(value){const title=this.getTitle();this.titlePromise=_jquery.default.Deferred(),this.asyncSet(value,title.html.bind(title)).then((()=>{this.titlePromise.resolve(title)})).catch(Notification.exception)}setBody(value){this.bodyPromise=_jquery.default.Deferred();const body=this.getBody();if("string"==typeof value)body.html(value),FilterEvents.notifyFilterContentUpdated(body),this.getRoot().trigger(_modal_events.default.bodyRendered,this),this.bodyPromise.resolve(body);else{const modalPromise=new _pending.default("amd-modal-js-pending-id-".concat(this.getModalCount()));let contentPromise=null;if(body.css("overflow","hidden"),"pending"==(value=_jquery.default.when(value)).state()){let height=body.innerHeight();height<100&&(height=100),body.animate({height:"".concat(height,"px")},150),body.html(""),contentPromise=Templates.render(TEMPLATES_LOADING,{}).then((html=>{const loadingIcon=(0,_jquery.default)(html).hide();return body.html(loadingIcon),loadingIcon.fadeIn(150),_jquery.default.when(loadingIcon.promise(),value)})).then((loadingIcon=>loadingIcon.fadeOut(100).promise())).then((()=>value))}else contentPromise=value;contentPromise.then(((html,js)=>{let result=null;if(this.isVisible()){body.css("opacity",0);const currentHeight=body.innerHeight();body.html(html),body.css("height","");const newHeight=body.innerHeight();body.css("height","".concat(currentHeight,"px")),result=body.animate({height:"".concat(newHeight,"px"),opacity:1},{duration:150,queue:!1}).promise()}else body.html(html);return js&&(this.isAttached?Templates.runTemplateJS(js):this.bodyJS=js),result})).then((result=>(FilterEvents.notifyFilterContentUpdated(body),this.getRoot().trigger(_modal_events.default.bodyRendered,this),result))).then((()=>{this.bodyPromise.resolve(body)})).catch(Notification.exception).always((()=>{body.css("height",""),body.css("overflow",""),body.css("opacity",""),modalPromise.resolve()}))}}setBodyContent(promise){return promise.then((_ref=>{let{html:html,js:js}=_ref;return this.setBody(_jquery.default.when(html,js))})).catch((exception=>{throw this.hide(),exception}))}setFooter(value){this.showFooter(),this.footerPromise=_jquery.default.Deferred();const footer=this.getFooter();"string"==typeof value?(footer.html(value),this.footerPromise.resolve(footer)):Templates.render(TEMPLATES_LOADING,{}).then((html=>(footer.html(html),value))).then(((html,js)=>(footer.html(html),js&&(this.isAttached?Templates.runTemplateJS(js):this.footerJS=js),footer))).then((footer=>{this.footerPromise.resolve(footer)})).catch(Notification.exception)}hasFooterContent(){return!!this.getFooter().children().length}hideFooter(){this.getFooter().addClass("hidden")}showFooter(){this.getFooter().removeClass("hidden")}setLarge(){this.isLarge()||this.getModal().addClass("modal-lg")}setVerticallyCentered(){this.isVerticallyCentered()||this.getModal().addClass("modal-dialog-centered")}isLarge(){return this.getModal().hasClass("modal-lg")}isVerticallyCentered(){return this.getModal().hasClass("modal-dialog-centered")}setSmall(){this.isSmall()||this.getModal().removeClass("modal-lg")}isSmall(){return!this.getModal().hasClass("modal-lg")}setScrollable(value){value?this.getModal()[0].classList.add("modal-dialog-scrollable"):this.getModal()[0].classList.remove("modal-dialog-scrollable")}calculateZIndex(){const items=(0,_jquery.default)("".concat(SELECTORS_DIALOG,", ").concat(SELECTORS_MENU_BAR,", ").concat(SELECTORS_HAS_Z_INDEX));let zIndex=parseInt(this.root.css("z-index"));return items.each(((index,item)=>{if(!(item=(0,_jquery.default)(item)).is(":visible"))return;const itemZIndex=item.css("z-index")?parseInt(item.css("z-index")):0;itemZIndex>zIndex&&(zIndex=itemZIndex)})),zIndex}isVisible(){return this.root.hasClass("show")}hasFocus(){const target=(0,_jquery.default)(document.activeElement);return this.root.is(target)||this.root.has(target).length}hasTransitions(){return this.getRoot().hasClass("fade")}getAttachmentPoint(){return(0,_jquery.default)(Fullscreen.getElement()||this.attachmentPoint)}show(){if(this.isVisible())return _jquery.default.Deferred().resolve();const pendingPromise=new _pending.default("core/modal:show");return this.hasFooterContent()?this.showFooter():this.hideFooter(),this.attachToDOM(),!this.focusOnClose&&document.activeElement&&(this.focusOnClose=document.activeElement),this.getBackdrop().then((backdrop=>{const newIndex=this.calculateZIndex()+2,newBackdropIndex=newIndex-1;this.root.css("z-index",newIndex),backdrop.setZIndex(newBackdropIndex),backdrop.show(),this.root.removeClass("hide").addClass("show"),this.accessibilityShow(),this.getModal().focus(),(0,_jquery.default)("body").addClass("modal-open"),this.root.trigger(_modal_events.default.shown,this)})).then(pendingPromise.resolve)}hideIfNotForm(){0==this.modal.find(SELECTORS_FORM).length&&this.hide()}hide(){this.getBackdrop().done((backdrop=>{FocusLock.untrapFocus(),this.countOtherVisibleModals()||(backdrop.hide(),(0,_jquery.default)("body").removeClass("modal-open"));const currentIndex=parseInt(this.root.css("z-index"));this.root.css("z-index",""),backdrop.setZIndex(currentIndex-3),this.accessibilityHide(),this.hasTransitions()?this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",(()=>{this.getRoot().removeClass("show").addClass("hide")})):this.getRoot().removeClass("show").addClass("hide"),(0,_jquery.default)(document.body).find(this.getRoot()).length&&(0,_jquery.default)(document.body).append(this.getRoot()),this.root.trigger(_modal_events.default.hidden,this)}))}destroy(){this.hide(),this.root.remove(),this.root.trigger(_modal_events.default.destroyed,this),this.attachmentPoint.remove()}accessibilityShow(){Aria.unhide(this.root.get()),Aria.hideSiblings(this.root.get()[0])}accessibilityHide(){Aria.unhideSiblings(this.root.get()[0]),Aria.hide(this.root.get())}registerEventListeners(){this.getRoot().on("keydown",(e=>{this.isVisible()&&e.keyCode==KeyCodes.escape&&(this.removeOnClose?this.destroy():this.hide())})),this.getRoot().click((e=>{if(!(0,_jquery.default)(e.target).closest(SELECTORS_MODAL).length&&(0,_jquery.default)(e.target).closest(SELECTORS_CONTAINER).length){const outsideClickEvent=_jquery.default.Event(_modal_events.default.outsideClick);this.getRoot().trigger(outsideClickEvent,this),outsideClickEvent.isDefaultPrevented()||this.hideIfNotForm()}})),CustomEvents.define(this.getModal(),[CustomEvents.events.activate]),this.getModal().on(CustomEvents.events.activate,SELECTORS_HIDE,((e,data)=>{this.removeOnClose?this.destroy():this.hide(),data.originalEvent.preventDefault()})),this.getRoot().on(_modal_events.default.hidden,(()=>{this.focusOnClose&&this.focusOnClose.focus()}))}registerCloseOnCancel(){this.getModal().on(CustomEvents.events.activate,this.getActionSelector("cancel"),((e,data)=>{const cancelEvent=_jquery.default.Event(_modal_events.default.cancel);this.getRoot().trigger(cancelEvent,this),cancelEvent.isDefaultPrevented()||(data.originalEvent.preventDefault(),this.removeOnClose?this.destroy():this.hide())}))}registerCloseOnSave(){this.getModal().on(CustomEvents.events.activate,this.getActionSelector("save"),((e,data)=>{const saveEvent=_jquery.default.Event(_modal_events.default.save);this.getRoot().trigger(saveEvent,this),saveEvent.isDefaultPrevented()||(data.originalEvent.preventDefault(),this.removeOnClose?this.destroy():this.hide())}))}registerCloseOnDelete(){this.getModal().on(CustomEvents.events.activate,this.getActionSelector("delete"),((e,data)=>{const deleteEvent=_jquery.default.Event(_modal_events.default.delete);this.getRoot().trigger(deleteEvent,this),deleteEvent.isDefaultPrevented()||(data.originalEvent.preventDefault(),this.removeOnClose?this.destroy():this.hide())}))}asyncSet(value,setFunction){return(value=>value instanceof Promise?_jquery.default.when(value):"object"==typeof value&&value.hasOwnProperty("then")?value:_jquery.default.Deferred().resolve(value))(value).then((content=>setFunction(content))).catch(Notification.exception)}setButtonText(action,value){const button=this.getFooter().find(this.getActionSelector(action));if(!button)throw new Error("Unable to find the '"+action+"' button");return this.asyncSet(value,button.text.bind(button))}getActionSelector(action){return"[data-action='"+action+"']"}setRemoveOnClose(remove){this.removeOnClose=remove}setReturnElement(element){this.focusOnClose=element}setButtonDisabled(action,disabled){const button=this.getFooter().find(this.getActionSelector(action));if(!button)throw new Error("Unable to find the '"+action+"' button");disabled?button.attr("disabled",""):button.removeAttr("disabled")}}return _exports.default=Modal,_defineProperty(Modal,"TEMPLATE","core/modal"),_defineProperty(Modal,"backdropPromise",null),_defineProperty(Modal,"modalCounter",0),_exports.default}));
//# sourceMappingURL=modal.min.js.map
\ No newline at end of file
diff --git a/lib/amd/build/modal.min.js.map b/lib/amd/build/modal.min.js.map
index 999f9826545..994728089b5 100644
--- a/lib/amd/build/modal.min.js.map
+++ b/lib/amd/build/modal.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"modal.min.js","sources":["../src/modal.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 .\n\n/**\n * Contain the logic for modals.\n *\n * @module core/modal\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as Templates from 'core/templates';\nimport * as Notification from 'core/notification';\nimport * as KeyCodes from 'core/key_codes';\nimport ModalBackdrop from 'core/modal_backdrop';\nimport ModalEvents from 'core/modal_events';\nimport * as ModalRegistry from 'core/modal_registry';\nimport Pending from 'core/pending';\nimport * as CustomEvents from 'core/custom_interaction_events';\nimport * as FilterEvents from 'core_filters/events';\nimport * as FocusLock from 'core/local/aria/focuslock';\nimport * as Aria from 'core/aria';\nimport * as Fullscreen from 'core/fullscreen';\n\nconst SELECTORS = {\n CONTAINER: '[data-region=\"modal-container\"]',\n MODAL: '[data-region=\"modal\"]',\n HEADER: '[data-region=\"header\"]',\n TITLE: '[data-region=\"title\"]',\n BODY: '[data-region=\"body\"]',\n FOOTER: '[data-region=\"footer\"]',\n HIDE: '[data-action=\"hide\"]',\n DIALOG: '[role=dialog]',\n FORM: 'form',\n MENU_BAR: '[role=menubar]',\n HAS_Z_INDEX: '.moodle-has-zindex',\n CAN_RECEIVE_FOCUS: 'input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]',\n};\n\nconst TEMPLATES = {\n LOADING: 'core/loading',\n BACKDROP: 'core/modal_backdrop',\n};\n\nexport default class Modal {\n /** @var {string} The template to use for this modal */\n static TEMPLATE = 'core/modal';\n\n /** @var {Promise} Module singleton for the backdrop to be reused by all Modal instances */\n static backdropPromise = null;\n\n /**\n * @var {Number} A counter that gets incremented for each modal created.\n * This can be used to generate unique values for the modals.\n */\n static modalCounter = 0;\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n constructor(root) {\n this.root = $(root);\n\n this.modal = this.root.find(SELECTORS.MODAL);\n this.header = this.modal.find(SELECTORS.HEADER);\n this.headerPromise = $.Deferred();\n this.title = this.header.find(SELECTORS.TITLE);\n this.titlePromise = $.Deferred();\n this.body = this.modal.find(SELECTORS.BODY);\n this.bodyPromise = $.Deferred();\n this.footer = this.modal.find(SELECTORS.FOOTER);\n this.footerPromise = $.Deferred();\n this.hiddenSiblings = [];\n this.isAttached = false;\n this.bodyJS = null;\n this.footerJS = null;\n this.modalCount = this.modalCounter++;\n this.attachmentPoint = document.createElement('div');\n document.body.append(this.attachmentPoint);\n this.focusOnClose = null;\n\n if (!this.root.is(SELECTORS.CONTAINER)) {\n Notification.exception({message: 'Element is not a modal container'});\n }\n\n if (!this.modal.length) {\n Notification.exception({message: 'Container does not contain a modal'});\n }\n\n if (!this.header.length) {\n Notification.exception({message: 'Modal is missing a header region'});\n }\n\n if (!this.title.length) {\n Notification.exception({message: 'Modal header is missing a title region'});\n }\n\n if (!this.body.length) {\n Notification.exception({message: 'Modal is missing a body region'});\n }\n\n if (!this.footer.length) {\n Notification.exception({message: 'Modal is missing a footer region'});\n }\n\n this.registerEventListeners();\n }\n\n /**\n * Register a modal with the modal registry.\n */\n static registerModalType() {\n if (!this.TYPE) {\n throw new Error(`Unknown modal type`, this);\n }\n\n if (!this.TEMPLATE) {\n throw new Error(`Unknown modal template`, this);\n }\n ModalRegistry.register(\n this.TYPE,\n this,\n this.TEMPLATE,\n );\n }\n\n /**\n * Attach the modal to the correct part of the page.\n *\n * If it hasn't already been added it runs any\n * javascript that has been cached until now.\n *\n * @method attachToDOM\n */\n attachToDOM() {\n this.getAttachmentPoint().append(this.root);\n\n if (this.isAttached) {\n return;\n }\n\n FocusLock.trapFocus(this.root[0]);\n\n // If we'd cached any JS then we can run it how that the modal is\n // attached to the DOM.\n if (this.bodyJS) {\n Templates.runTemplateJS(this.bodyJS);\n this.bodyJS = null;\n }\n\n if (this.footerJS) {\n Templates.runTemplateJS(this.footerJS);\n this.footerJS = null;\n }\n\n this.isAttached = true;\n }\n\n /**\n * Count the number of other visible modals (not including this one).\n *\n * @method countOtherVisibleModals\n * @return {int}\n */\n countOtherVisibleModals() {\n let count = 0;\n $('body').find(SELECTORS.CONTAINER).each((index, element) => {\n element = $(element);\n\n // If we haven't found ourself and the element is visible.\n if (!this.root.is(element) && element.hasClass('show')) {\n count++;\n }\n });\n\n return count;\n }\n\n /**\n * Get the modal backdrop.\n *\n * @method getBackdrop\n * @return {object} jQuery promise\n */\n getBackdrop() {\n if (!Modal.backdropPromise) {\n Modal.backdropPromise = Templates.render(TEMPLATES.BACKDROP, {})\n .then((html) => new ModalBackdrop($(html)))\n .catch(Notification.exception);\n }\n\n return Modal.backdropPromise;\n }\n\n /**\n * Get the root element of this modal.\n *\n * @method getRoot\n * @return {object} jQuery object\n */\n getRoot() {\n return this.root;\n }\n\n /**\n * Get the modal element of this modal.\n *\n * @method getModal\n * @return {object} jQuery object\n */\n getModal() {\n return this.modal;\n }\n\n /**\n * Get the modal title element.\n *\n * @method getTitle\n * @return {object} jQuery object\n */\n getTitle() {\n return this.title;\n }\n\n /**\n * Get the modal body element.\n *\n * @method getBody\n * @return {object} jQuery object\n */\n getBody() {\n return this.body;\n }\n\n /**\n * Get the modal footer element.\n *\n * @method getFooter\n * @return {object} jQuery object\n */\n getFooter() {\n return this.footer;\n }\n\n /**\n * Get a promise resolving to the title region.\n *\n * @method getTitlePromise\n * @return {Promise}\n */\n getTitlePromise() {\n return this.titlePromise;\n }\n\n /**\n * Get a promise resolving to the body region.\n *\n * @method getBodyPromise\n * @return {object} jQuery object\n */\n getBodyPromise() {\n return this.bodyPromise;\n }\n\n /**\n * Get a promise resolving to the footer region.\n *\n * @method getFooterPromise\n * @return {object} jQuery object\n */\n getFooterPromise() {\n return this.footerPromise;\n }\n\n /**\n * Get the unique modal count.\n *\n * @method getModalCount\n * @return {int}\n */\n getModalCount() {\n return this.modalCount;\n }\n\n /**\n * Set the modal title element.\n *\n * This method is overloaded to take either a string value for the title or a jQuery promise that is resolved with\n * HTML most commonly from a Str.get_string call.\n *\n * @method setTitle\n * @param {(string|object)} value The title string or jQuery promise which resolves to the title.\n */\n setTitle(value) {\n const title = this.getTitle();\n this.titlePromise = $.Deferred();\n\n this.asyncSet(value, title.html.bind(title))\n .then(() => {\n this.titlePromise.resolve(title);\n return;\n })\n .catch(Notification.exception);\n }\n\n /**\n * Set the modal body element.\n *\n * This method is overloaded to take either a string value for the body or a jQuery promise that is resolved with\n * HTML and Javascript most commonly from a Templates.render call.\n *\n * @method setBody\n * @param {(string|object)} value The body string or jQuery promise which resolves to the body.\n * @fires event:filterContentUpdated\n */\n setBody(value) {\n this.bodyPromise = $.Deferred();\n\n const body = this.getBody();\n\n if (typeof value === 'string') {\n // Just set the value if it's a string.\n body.html(value);\n FilterEvents.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n this.bodyPromise.resolve(body);\n } else {\n const modalPromise = new Pending(`amd-modal-js-pending-id-${this.getModalCount()}`);\n // Otherwise we assume it's a promise to be resolved with\n // html and javascript.\n let contentPromise = null;\n body.css('overflow', 'hidden');\n\n // Ensure that the `value` is a jQuery Promise.\n value = $.when(value);\n\n if (value.state() == 'pending') {\n // We're still waiting for the body promise to resolve so\n // let's show a loading icon.\n let height = body.innerHeight();\n if (height < 100) {\n height = 100;\n }\n\n body.animate({height: `${height}px`}, 150);\n\n body.html('');\n contentPromise = Templates.render(TEMPLATES.LOADING, {})\n .then((html) => {\n const loadingIcon = $(html).hide();\n body.html(loadingIcon);\n loadingIcon.fadeIn(150);\n\n // We only want the loading icon to fade out\n // when the content for the body has finished\n // loading.\n return $.when(loadingIcon.promise(), value);\n })\n .then((loadingIcon) => {\n // Once the content has finished loading and\n // the loading icon has been shown then we can\n // fade the icon away to reveal the content.\n return loadingIcon.fadeOut(100).promise();\n })\n .then(() => {\n return value;\n });\n } else {\n // The content is already loaded so let's just display\n // it to the user. No need for a loading icon.\n contentPromise = value;\n }\n\n // Now we can actually display the content.\n contentPromise.then((html, js) => {\n let result = null;\n\n if (this.isVisible()) {\n // If the modal is visible then we should display\n // the content gracefully for the user.\n body.css('opacity', 0);\n const currentHeight = body.innerHeight();\n body.html(html);\n // We need to clear any height values we've set here\n // in order to measure the height of the content being\n // added. This then allows us to animate the height\n // transition.\n body.css('height', '');\n const newHeight = body.innerHeight();\n body.css('height', `${currentHeight}px`);\n result = body.animate(\n {height: `${newHeight}px`, opacity: 1},\n {duration: 150, queue: false}\n ).promise();\n } else {\n // Since the modal isn't visible we can just immediately\n // set the content. No need to animate it.\n body.html(html);\n }\n\n if (js) {\n if (this.isAttached) {\n // If we're in the DOM then run the JS immediately.\n Templates.runTemplateJS(js);\n } else {\n // Otherwise cache it to be run when we're attached.\n this.bodyJS = js;\n }\n }\n\n return result;\n })\n .then((result) => {\n FilterEvents.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n return result;\n })\n .then(() => {\n this.bodyPromise.resolve(body);\n return;\n })\n .catch(Notification.exception)\n .always(() => {\n // When we're done displaying all of the content we need\n // to clear the custom values we've set here.\n body.css('height', '');\n body.css('overflow', '');\n body.css('opacity', '');\n modalPromise.resolve();\n\n return;\n });\n }\n }\n\n /**\n * Alternative to setBody() that can be used from non-Jquery modules\n *\n * @param {Promise} promise promise that returns {html, js} object\n * @return {Promise}\n */\n setBodyContent(promise) {\n // Call the leegacy API for now and pass it a jQuery Promise.\n // This is a non-spec feature of jQuery and cannot be produced with spec promises.\n // We can encourage people to migrate to this approach, and in future we can swap\n // it so that setBody() calls setBodyPromise().\n return promise.then(({html, js}) => this.setBody($.when(html, js)))\n .catch(exception => {\n this.hide();\n throw exception;\n });\n }\n\n /**\n * Set the modal footer element. The footer element is made visible, if it\n * isn't already.\n *\n * This method is overloaded to take either a string\n * value for the body or a jQuery promise that is resolved with HTML and Javascript\n * most commonly from a Templates.render call.\n *\n * @method setFooter\n * @param {(string|object)} value The footer string or jQuery promise\n */\n setFooter(value) {\n // Make sure the footer is visible.\n this.showFooter();\n this.footerPromise = $.Deferred();\n\n const footer = this.getFooter();\n\n if (typeof value === 'string') {\n // Just set the value if it's a string.\n footer.html(value);\n this.footerPromise.resolve(footer);\n } else {\n // Otherwise we assume it's a promise to be resolved with\n // html and javascript.\n Templates.render(TEMPLATES.LOADING, {})\n .then((html) => {\n footer.html(html);\n\n return value;\n })\n .then((html, js) => {\n footer.html(html);\n\n if (js) {\n if (this.isAttached) {\n // If we're in the DOM then run the JS immediately.\n Templates.runTemplateJS(js);\n } else {\n // Otherwise cache it to be run when we're attached.\n this.footerJS = js;\n }\n }\n\n return footer;\n })\n .then((footer) => {\n this.footerPromise.resolve(footer);\n return;\n })\n .catch(Notification.exception);\n }\n }\n\n /**\n * Check if the footer has any content in it.\n *\n * @method hasFooterContent\n * @return {bool}\n */\n hasFooterContent() {\n return this.getFooter().children().length ? true : false;\n }\n\n /**\n * Hide the footer element.\n *\n * @method hideFooter\n */\n hideFooter() {\n this.getFooter().addClass('hidden');\n }\n\n /**\n * Show the footer element.\n *\n * @method showFooter\n */\n showFooter() {\n this.getFooter().removeClass('hidden');\n }\n\n /**\n * Mark the modal as a large modal.\n *\n * @method setLarge\n */\n setLarge() {\n if (this.isLarge()) {\n return;\n }\n\n this.getModal().addClass('modal-lg');\n }\n\n /**\n * Mark the modal as a centered modal.\n *\n * @method setVerticallyCentered\n */\n setVerticallyCentered() {\n if (this.isVerticallyCentered()) {\n return;\n }\n this.getModal().addClass('modal-dialog-centered');\n }\n\n /**\n * Check if the modal is a large modal.\n *\n * @method isLarge\n * @return {bool}\n */\n isLarge() {\n return this.getModal().hasClass('modal-lg');\n }\n\n /**\n * Check if the modal is vertically centered.\n *\n * @method isVerticallyCentered\n * @return {bool}\n */\n isVerticallyCentered() {\n return this.getModal().hasClass('modal-dialog-centered');\n }\n\n /**\n * Mark the modal as a small modal.\n *\n * @method setSmall\n */\n setSmall() {\n if (this.isSmall()) {\n return;\n }\n\n this.getModal().removeClass('modal-lg');\n }\n\n /**\n * Check if the modal is a small modal.\n *\n * @method isSmall\n * @return {bool}\n */\n isSmall() {\n return !this.getModal().hasClass('modal-lg');\n }\n\n /**\n * Set this modal to be scrollable or not.\n *\n * @method setScrollable\n * @param {bool} value Whether the modal is scrollable or not\n */\n setScrollable(value) {\n if (!value) {\n this.getModal()[0].classList.remove('modal-dialog-scrollable');\n return;\n }\n\n this.getModal()[0].classList.add('modal-dialog-scrollable');\n }\n\n\n /**\n * Determine the highest z-index value currently on the page.\n *\n * @method calculateZIndex\n * @return {int}\n */\n calculateZIndex() {\n const items = $(`${SELECTORS.DIALOG}, ${SELECTORS.MENU_BAR}, ${SELECTORS.HAS_Z_INDEX}`);\n let zIndex = parseInt(this.root.css('z-index'));\n\n items.each((index, item) => {\n item = $(item);\n if (!item.is(':visible')) {\n // Do not include items which are not visible in the z-index calculation.\n // This is important because some dialogues are not removed from the DOM.\n return;\n }\n // Note that webkit browsers won't return the z-index value from the CSS stylesheet\n // if the element doesn't have a position specified. Instead it'll return \"auto\".\n const itemZIndex = item.css('z-index') ? parseInt(item.css('z-index')) : 0;\n\n if (itemZIndex > zIndex) {\n zIndex = itemZIndex;\n }\n });\n\n return zIndex;\n }\n\n /**\n * Check if this modal is visible.\n *\n * @method isVisible\n * @return {bool}\n */\n isVisible() {\n return this.root.hasClass('show');\n }\n\n /**\n * Check if this modal has focus.\n *\n * @method hasFocus\n * @return {bool}\n */\n hasFocus() {\n const target = $(document.activeElement);\n return this.root.is(target) || this.root.has(target).length;\n }\n\n /**\n * Check if this modal has CSS transitions applied.\n *\n * @method hasTransitions\n * @return {bool}\n */\n hasTransitions() {\n return this.getRoot().hasClass('fade');\n }\n\n /**\n * Gets the jQuery wrapped node that the Modal should be attached to.\n *\n * @returns {jQuery}\n */\n getAttachmentPoint() {\n return $(Fullscreen.getElement() || this.attachmentPoint);\n }\n\n /**\n * Display this modal. The modal will be attached to the DOM if it hasn't\n * already been.\n *\n * @method show\n * @returns {Promise}\n */\n show() {\n if (this.isVisible()) {\n return $.Deferred().resolve();\n }\n\n const pendingPromise = new Pending('core/modal:show');\n\n if (this.hasFooterContent()) {\n this.showFooter();\n } else {\n this.hideFooter();\n }\n\n this.attachToDOM();\n\n // If the focusOnClose was not set. Set the focus back to triggered element.\n if (!this.focusOnClose && document.activeElement) {\n this.focusOnClose = document.activeElement;\n }\n\n return this.getBackdrop()\n .then((backdrop) => {\n const currentIndex = this.calculateZIndex();\n const newIndex = currentIndex + 2;\n const newBackdropIndex = newIndex - 1;\n this.root.css('z-index', newIndex);\n backdrop.setZIndex(newBackdropIndex);\n backdrop.show();\n\n this.root.removeClass('hide').addClass('show');\n this.accessibilityShow();\n this.getModal().focus();\n $('body').addClass('modal-open');\n this.root.trigger(ModalEvents.shown, this);\n\n return;\n })\n .then(pendingPromise.resolve);\n }\n\n /**\n * Hide this modal if it does not contain a form.\n *\n * @method hideIfNotForm\n */\n hideIfNotForm() {\n const formElement = this.modal.find(SELECTORS.FORM);\n if (formElement.length == 0) {\n this.hide();\n }\n }\n\n /**\n * Hide this modal.\n *\n * @method hide\n */\n hide() {\n this.getBackdrop().done((backdrop) => {\n FocusLock.untrapFocus();\n\n if (!this.countOtherVisibleModals()) {\n // Hide the backdrop if we're the last open modal.\n backdrop.hide();\n $('body').removeClass('modal-open');\n }\n\n const currentIndex = parseInt(this.root.css('z-index'));\n this.root.css('z-index', '');\n backdrop.setZIndex(currentIndex - 3);\n\n this.accessibilityHide();\n\n if (this.hasTransitions()) {\n // Wait for CSS transitions to complete before hiding the element.\n this.getRoot().one('transitionend webkitTransitionEnd oTransitionEnd', () => {\n this.getRoot().removeClass('show').addClass('hide');\n });\n } else {\n this.getRoot().removeClass('show').addClass('hide');\n }\n\n // Ensure the modal is moved onto the body node if it is still attached to the DOM.\n if ($(document.body).find(this.getRoot()).length) {\n $(document.body).append(this.getRoot());\n }\n\n this.root.trigger(ModalEvents.hidden, this);\n });\n }\n\n /**\n * Remove this modal from the DOM.\n *\n * @method destroy\n */\n destroy() {\n this.hide();\n this.root.remove();\n this.root.trigger(ModalEvents.destroyed, this);\n this.attachmentPoint.remove();\n }\n\n /**\n * Sets the appropriate aria attributes on this dialogue and the other\n * elements in the DOM to ensure that screen readers are able to navigate\n * the dialogue popup correctly.\n *\n * @method accessibilityShow\n */\n accessibilityShow() {\n // Make us visible to screen readers.\n Aria.unhide(this.root.get());\n\n // Hide siblings.\n Aria.hideSiblings(this.root.get()[0]);\n }\n\n /**\n * Restores the aria visibility on the DOM elements changed when displaying\n * the dialogue popup and makes the dialogue aria hidden to allow screen\n * readers to navigate the main page correctly when the dialogue is closed.\n *\n * @method accessibilityHide\n */\n accessibilityHide() {\n // Unhide siblings.\n Aria.unhideSiblings(this.root.get()[0]);\n\n // Hide this modal.\n Aria.hide(this.root.get());\n }\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n registerEventListeners() {\n this.getRoot().on('keydown', (e) => {\n if (!this.isVisible()) {\n return;\n }\n\n if (e.keyCode == KeyCodes.escape) {\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n\n // Listen for clicks on the modal container.\n this.getRoot().click((e) => {\n // If the click wasn't inside the modal element then we should\n // hide the modal.\n if (!$(e.target).closest(SELECTORS.MODAL).length) {\n // The check above fails to detect the click was inside the modal when the DOM tree is already changed.\n // So, we check if we can still find the container element or not. If not, then the DOM tree is changed.\n // It's best not to hide the modal in that case.\n if ($(e.target).closest(SELECTORS.CONTAINER).length) {\n const outsideClickEvent = $.Event(ModalEvents.outsideClick);\n this.getRoot().trigger(outsideClickEvent, this);\n\n if (!outsideClickEvent.isDefaultPrevented()) {\n this.hideIfNotForm();\n }\n }\n }\n });\n\n CustomEvents.define(this.getModal(), [CustomEvents.events.activate]);\n this.getModal().on(CustomEvents.events.activate, SELECTORS.HIDE, (e, data) => {\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n data.originalEvent.preventDefault();\n });\n\n this.getRoot().on(ModalEvents.hidden, () => {\n if (this.focusOnClose) {\n // Focus on the element that actually triggers the modal.\n this.focusOnClose.focus();\n }\n });\n }\n\n /**\n * Register a listener to close the dialogue when the cancel button is pressed.\n *\n * @method registerCloseOnCancel\n */\n registerCloseOnCancel() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('cancel'), (e, data) => {\n const cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n data.originalEvent.preventDefault();\n\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n }\n\n /**\n * Register a listener to close the dialogue when the save button is pressed.\n *\n * @method registerCloseOnSave\n */\n registerCloseOnSave() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('save'), (e, data) => {\n const saveEvent = $.Event(ModalEvents.save);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n data.originalEvent.preventDefault();\n\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n }\n\n\n /**\n * Register a listener to close the dialogue when the delete button is pressed.\n *\n * @method registerCloseOnDelete\n */\n registerCloseOnDelete() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('delete'), (e, data) => {\n const deleteEvent = $.Event(ModalEvents.delete);\n this.getRoot().trigger(deleteEvent, this);\n\n if (!deleteEvent.isDefaultPrevented()) {\n data.originalEvent.preventDefault();\n\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n }\n\n /**\n * Set or resolve and set the value using the function.\n *\n * @method asyncSet\n * @param {(string|object)} value The string or jQuery promise.\n * @param {function} setFunction The setter\n * @return {Promise}\n */\n asyncSet(value, setFunction) {\n const getWrappedValue = (value) => {\n if (value instanceof Promise) {\n return $.when(value);\n }\n\n if (typeof value !== 'object' || !value.hasOwnProperty('then')) {\n return $.Deferred().resolve(value);\n }\n\n return value;\n };\n\n return getWrappedValue(value)\n .then((content) => setFunction(content))\n .catch(Notification.exception);\n }\n\n /**\n * Set the title text of a button.\n *\n * This method is overloaded to take either a string value for the button title or a jQuery promise that is resolved with\n * text most commonly from a Str.get_string call.\n *\n * @param {DOMString} action The action of the button\n * @param {(String|object)} value The button text, or a promise which will resolve to it\n * @returns {Promise}\n */\n setButtonText(action, value) {\n const button = this.getFooter().find(this.getActionSelector(action));\n\n if (!button) {\n throw new Error(\"Unable to find the '\" + action + \"' button\");\n }\n\n return this.asyncSet(value, button.text.bind(button));\n }\n\n /**\n * Get the Selector for an action.\n *\n * @param {String} action\n * @returns {DOMString}\n */\n getActionSelector(action) {\n return \"[data-action='\" + action + \"']\";\n }\n\n /**\n * Set the flag to remove the modal from the DOM on close.\n *\n * @param {Boolean} remove\n */\n setRemoveOnClose(remove) {\n this.removeOnClose = remove;\n }\n\n /**\n * Set the return element for the modal.\n *\n * @param {Element|jQuery} element Element to focus when the modal is closed\n */\n setReturnElement(element) {\n this.focusOnClose = element;\n }\n\n /**\n * Set the a button enabled or disabled.\n *\n * @param {DOMString} action The action of the button\n * @param {Boolean} disabled the new disabled value\n */\n setButtonDisabled(action, disabled) {\n const button = this.getFooter().find(this.getActionSelector(action));\n\n if (!button) {\n throw new Error(\"Unable to find the '\" + action + \"' button\");\n }\n if (disabled) {\n button.attr('disabled', '');\n } else {\n button.removeAttr('disabled');\n }\n }\n}\n"],"names":["SELECTORS","TEMPLATES","Modal","constructor","root","modal","this","find","header","headerPromise","$","Deferred","title","titlePromise","body","bodyPromise","footer","footerPromise","hiddenSiblings","isAttached","bodyJS","footerJS","modalCount","modalCounter","attachmentPoint","document","createElement","append","focusOnClose","is","Notification","exception","message","length","registerEventListeners","TYPE","Error","TEMPLATE","ModalRegistry","register","attachToDOM","getAttachmentPoint","FocusLock","trapFocus","Templates","runTemplateJS","countOtherVisibleModals","count","each","index","element","hasClass","getBackdrop","backdropPromise","render","then","html","ModalBackdrop","catch","getRoot","getModal","getTitle","getBody","getFooter","getTitlePromise","getBodyPromise","getFooterPromise","getModalCount","setTitle","value","asyncSet","bind","resolve","setBody","FilterEvents","notifyFilterContentUpdated","trigger","ModalEvents","bodyRendered","modalPromise","Pending","contentPromise","css","when","state","height","innerHeight","animate","loadingIcon","hide","fadeIn","promise","fadeOut","js","result","isVisible","currentHeight","newHeight","opacity","duration","queue","always","setBodyContent","_ref","setFooter","showFooter","hasFooterContent","children","hideFooter","addClass","removeClass","setLarge","isLarge","setVerticallyCentered","isVerticallyCentered","setSmall","isSmall","setScrollable","classList","add","remove","calculateZIndex","items","zIndex","parseInt","item","itemZIndex","hasFocus","target","activeElement","has","hasTransitions","Fullscreen","getElement","show","pendingPromise","backdrop","newIndex","newBackdropIndex","setZIndex","accessibilityShow","focus","shown","hideIfNotForm","done","untrapFocus","currentIndex","accessibilityHide","one","hidden","destroy","destroyed","Aria","unhide","get","hideSiblings","unhideSiblings","on","e","keyCode","KeyCodes","escape","removeOnClose","click","closest","outsideClickEvent","Event","outsideClick","isDefaultPrevented","CustomEvents","define","events","activate","data","originalEvent","preventDefault","registerCloseOnCancel","getActionSelector","cancelEvent","cancel","registerCloseOnSave","saveEvent","save","registerCloseOnDelete","deleteEvent","delete","setFunction","Promise","hasOwnProperty","getWrappedValue","content","setButtonText","action","button","text","setRemoveOnClose","setReturnElement","setButtonDisabled","disabled","attr","removeAttr"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"modal.min.js","sources":["../src/modal.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 .\n\n/**\n * Contain the logic for modals.\n *\n * @module core/modal\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as Templates from 'core/templates';\nimport * as Notification from 'core/notification';\nimport * as KeyCodes from 'core/key_codes';\nimport ModalBackdrop from 'core/modal_backdrop';\nimport ModalEvents from 'core/modal_events';\nimport * as ModalRegistry from 'core/modal_registry';\nimport Pending from 'core/pending';\nimport * as CustomEvents from 'core/custom_interaction_events';\nimport * as FilterEvents from 'core_filters/events';\nimport * as FocusLock from 'core/local/aria/focuslock';\nimport * as Aria from 'core/aria';\nimport * as Fullscreen from 'core/fullscreen';\n\nconst SELECTORS = {\n CONTAINER: '[data-region=\"modal-container\"]',\n MODAL: '[data-region=\"modal\"]',\n HEADER: '[data-region=\"header\"]',\n TITLE: '[data-region=\"title\"]',\n BODY: '[data-region=\"body\"]',\n FOOTER: '[data-region=\"footer\"]',\n HIDE: '[data-action=\"hide\"]',\n DIALOG: '[role=dialog]',\n FORM: 'form',\n MENU_BAR: '[role=menubar]',\n HAS_Z_INDEX: '.moodle-has-zindex',\n CAN_RECEIVE_FOCUS: 'input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]',\n};\n\nconst TEMPLATES = {\n LOADING: 'core/loading',\n BACKDROP: 'core/modal_backdrop',\n};\n\nexport default class Modal {\n /** @var {string} The template to use for this modal */\n static TEMPLATE = 'core/modal';\n\n /** @var {Promise} Module singleton for the backdrop to be reused by all Modal instances */\n static backdropPromise = null;\n\n /**\n * @var {Number} A counter that gets incremented for each modal created.\n * This can be used to generate unique values for the modals.\n */\n static modalCounter = 0;\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n constructor(root) {\n this.root = $(root);\n\n this.modal = this.root.find(SELECTORS.MODAL);\n this.header = this.modal.find(SELECTORS.HEADER);\n this.headerPromise = $.Deferred();\n this.title = this.header.find(SELECTORS.TITLE);\n this.titlePromise = $.Deferred();\n this.body = this.modal.find(SELECTORS.BODY);\n this.bodyPromise = $.Deferred();\n this.footer = this.modal.find(SELECTORS.FOOTER);\n this.footerPromise = $.Deferred();\n this.hiddenSiblings = [];\n this.isAttached = false;\n this.bodyJS = null;\n this.footerJS = null;\n this.modalCount = Modal.modalCounter++;\n this.attachmentPoint = document.createElement('div');\n document.body.append(this.attachmentPoint);\n this.focusOnClose = null;\n\n if (!this.root.is(SELECTORS.CONTAINER)) {\n Notification.exception({message: 'Element is not a modal container'});\n }\n\n if (!this.modal.length) {\n Notification.exception({message: 'Container does not contain a modal'});\n }\n\n if (!this.header.length) {\n Notification.exception({message: 'Modal is missing a header region'});\n }\n\n if (!this.title.length) {\n Notification.exception({message: 'Modal header is missing a title region'});\n }\n\n if (!this.body.length) {\n Notification.exception({message: 'Modal is missing a body region'});\n }\n\n if (!this.footer.length) {\n Notification.exception({message: 'Modal is missing a footer region'});\n }\n\n this.registerEventListeners();\n }\n\n /**\n * Register a modal with the modal registry.\n */\n static registerModalType() {\n if (!this.TYPE) {\n throw new Error(`Unknown modal type`, this);\n }\n\n if (!this.TEMPLATE) {\n throw new Error(`Unknown modal template`, this);\n }\n ModalRegistry.register(\n this.TYPE,\n this,\n this.TEMPLATE,\n );\n }\n\n /**\n * Attach the modal to the correct part of the page.\n *\n * If it hasn't already been added it runs any\n * javascript that has been cached until now.\n *\n * @method attachToDOM\n */\n attachToDOM() {\n this.getAttachmentPoint().append(this.root);\n\n if (this.isAttached) {\n return;\n }\n\n FocusLock.trapFocus(this.root[0]);\n\n // If we'd cached any JS then we can run it how that the modal is\n // attached to the DOM.\n if (this.bodyJS) {\n Templates.runTemplateJS(this.bodyJS);\n this.bodyJS = null;\n }\n\n if (this.footerJS) {\n Templates.runTemplateJS(this.footerJS);\n this.footerJS = null;\n }\n\n this.isAttached = true;\n }\n\n /**\n * Count the number of other visible modals (not including this one).\n *\n * @method countOtherVisibleModals\n * @return {int}\n */\n countOtherVisibleModals() {\n let count = 0;\n $('body').find(SELECTORS.CONTAINER).each((index, element) => {\n element = $(element);\n\n // If we haven't found ourself and the element is visible.\n if (!this.root.is(element) && element.hasClass('show')) {\n count++;\n }\n });\n\n return count;\n }\n\n /**\n * Get the modal backdrop.\n *\n * @method getBackdrop\n * @return {object} jQuery promise\n */\n getBackdrop() {\n if (!Modal.backdropPromise) {\n Modal.backdropPromise = Templates.render(TEMPLATES.BACKDROP, {})\n .then((html) => new ModalBackdrop($(html)))\n .catch(Notification.exception);\n }\n\n return Modal.backdropPromise;\n }\n\n /**\n * Get the root element of this modal.\n *\n * @method getRoot\n * @return {object} jQuery object\n */\n getRoot() {\n return this.root;\n }\n\n /**\n * Get the modal element of this modal.\n *\n * @method getModal\n * @return {object} jQuery object\n */\n getModal() {\n return this.modal;\n }\n\n /**\n * Get the modal title element.\n *\n * @method getTitle\n * @return {object} jQuery object\n */\n getTitle() {\n return this.title;\n }\n\n /**\n * Get the modal body element.\n *\n * @method getBody\n * @return {object} jQuery object\n */\n getBody() {\n return this.body;\n }\n\n /**\n * Get the modal footer element.\n *\n * @method getFooter\n * @return {object} jQuery object\n */\n getFooter() {\n return this.footer;\n }\n\n /**\n * Get a promise resolving to the title region.\n *\n * @method getTitlePromise\n * @return {Promise}\n */\n getTitlePromise() {\n return this.titlePromise;\n }\n\n /**\n * Get a promise resolving to the body region.\n *\n * @method getBodyPromise\n * @return {object} jQuery object\n */\n getBodyPromise() {\n return this.bodyPromise;\n }\n\n /**\n * Get a promise resolving to the footer region.\n *\n * @method getFooterPromise\n * @return {object} jQuery object\n */\n getFooterPromise() {\n return this.footerPromise;\n }\n\n /**\n * Get the unique modal count.\n *\n * @method getModalCount\n * @return {int}\n */\n getModalCount() {\n return this.modalCount;\n }\n\n /**\n * Set the modal title element.\n *\n * This method is overloaded to take either a string value for the title or a jQuery promise that is resolved with\n * HTML most commonly from a Str.get_string call.\n *\n * @method setTitle\n * @param {(string|object)} value The title string or jQuery promise which resolves to the title.\n */\n setTitle(value) {\n const title = this.getTitle();\n this.titlePromise = $.Deferred();\n\n this.asyncSet(value, title.html.bind(title))\n .then(() => {\n this.titlePromise.resolve(title);\n return;\n })\n .catch(Notification.exception);\n }\n\n /**\n * Set the modal body element.\n *\n * This method is overloaded to take either a string value for the body or a jQuery promise that is resolved with\n * HTML and Javascript most commonly from a Templates.render call.\n *\n * @method setBody\n * @param {(string|object)} value The body string or jQuery promise which resolves to the body.\n * @fires event:filterContentUpdated\n */\n setBody(value) {\n this.bodyPromise = $.Deferred();\n\n const body = this.getBody();\n\n if (typeof value === 'string') {\n // Just set the value if it's a string.\n body.html(value);\n FilterEvents.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n this.bodyPromise.resolve(body);\n } else {\n const modalPromise = new Pending(`amd-modal-js-pending-id-${this.getModalCount()}`);\n // Otherwise we assume it's a promise to be resolved with\n // html and javascript.\n let contentPromise = null;\n body.css('overflow', 'hidden');\n\n // Ensure that the `value` is a jQuery Promise.\n value = $.when(value);\n\n if (value.state() == 'pending') {\n // We're still waiting for the body promise to resolve so\n // let's show a loading icon.\n let height = body.innerHeight();\n if (height < 100) {\n height = 100;\n }\n\n body.animate({height: `${height}px`}, 150);\n\n body.html('');\n contentPromise = Templates.render(TEMPLATES.LOADING, {})\n .then((html) => {\n const loadingIcon = $(html).hide();\n body.html(loadingIcon);\n loadingIcon.fadeIn(150);\n\n // We only want the loading icon to fade out\n // when the content for the body has finished\n // loading.\n return $.when(loadingIcon.promise(), value);\n })\n .then((loadingIcon) => {\n // Once the content has finished loading and\n // the loading icon has been shown then we can\n // fade the icon away to reveal the content.\n return loadingIcon.fadeOut(100).promise();\n })\n .then(() => {\n return value;\n });\n } else {\n // The content is already loaded so let's just display\n // it to the user. No need for a loading icon.\n contentPromise = value;\n }\n\n // Now we can actually display the content.\n contentPromise.then((html, js) => {\n let result = null;\n\n if (this.isVisible()) {\n // If the modal is visible then we should display\n // the content gracefully for the user.\n body.css('opacity', 0);\n const currentHeight = body.innerHeight();\n body.html(html);\n // We need to clear any height values we've set here\n // in order to measure the height of the content being\n // added. This then allows us to animate the height\n // transition.\n body.css('height', '');\n const newHeight = body.innerHeight();\n body.css('height', `${currentHeight}px`);\n result = body.animate(\n {height: `${newHeight}px`, opacity: 1},\n {duration: 150, queue: false}\n ).promise();\n } else {\n // Since the modal isn't visible we can just immediately\n // set the content. No need to animate it.\n body.html(html);\n }\n\n if (js) {\n if (this.isAttached) {\n // If we're in the DOM then run the JS immediately.\n Templates.runTemplateJS(js);\n } else {\n // Otherwise cache it to be run when we're attached.\n this.bodyJS = js;\n }\n }\n\n return result;\n })\n .then((result) => {\n FilterEvents.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n return result;\n })\n .then(() => {\n this.bodyPromise.resolve(body);\n return;\n })\n .catch(Notification.exception)\n .always(() => {\n // When we're done displaying all of the content we need\n // to clear the custom values we've set here.\n body.css('height', '');\n body.css('overflow', '');\n body.css('opacity', '');\n modalPromise.resolve();\n\n return;\n });\n }\n }\n\n /**\n * Alternative to setBody() that can be used from non-Jquery modules\n *\n * @param {Promise} promise promise that returns {html, js} object\n * @return {Promise}\n */\n setBodyContent(promise) {\n // Call the leegacy API for now and pass it a jQuery Promise.\n // This is a non-spec feature of jQuery and cannot be produced with spec promises.\n // We can encourage people to migrate to this approach, and in future we can swap\n // it so that setBody() calls setBodyPromise().\n return promise.then(({html, js}) => this.setBody($.when(html, js)))\n .catch(exception => {\n this.hide();\n throw exception;\n });\n }\n\n /**\n * Set the modal footer element. The footer element is made visible, if it\n * isn't already.\n *\n * This method is overloaded to take either a string\n * value for the body or a jQuery promise that is resolved with HTML and Javascript\n * most commonly from a Templates.render call.\n *\n * @method setFooter\n * @param {(string|object)} value The footer string or jQuery promise\n */\n setFooter(value) {\n // Make sure the footer is visible.\n this.showFooter();\n this.footerPromise = $.Deferred();\n\n const footer = this.getFooter();\n\n if (typeof value === 'string') {\n // Just set the value if it's a string.\n footer.html(value);\n this.footerPromise.resolve(footer);\n } else {\n // Otherwise we assume it's a promise to be resolved with\n // html and javascript.\n Templates.render(TEMPLATES.LOADING, {})\n .then((html) => {\n footer.html(html);\n\n return value;\n })\n .then((html, js) => {\n footer.html(html);\n\n if (js) {\n if (this.isAttached) {\n // If we're in the DOM then run the JS immediately.\n Templates.runTemplateJS(js);\n } else {\n // Otherwise cache it to be run when we're attached.\n this.footerJS = js;\n }\n }\n\n return footer;\n })\n .then((footer) => {\n this.footerPromise.resolve(footer);\n return;\n })\n .catch(Notification.exception);\n }\n }\n\n /**\n * Check if the footer has any content in it.\n *\n * @method hasFooterContent\n * @return {bool}\n */\n hasFooterContent() {\n return this.getFooter().children().length ? true : false;\n }\n\n /**\n * Hide the footer element.\n *\n * @method hideFooter\n */\n hideFooter() {\n this.getFooter().addClass('hidden');\n }\n\n /**\n * Show the footer element.\n *\n * @method showFooter\n */\n showFooter() {\n this.getFooter().removeClass('hidden');\n }\n\n /**\n * Mark the modal as a large modal.\n *\n * @method setLarge\n */\n setLarge() {\n if (this.isLarge()) {\n return;\n }\n\n this.getModal().addClass('modal-lg');\n }\n\n /**\n * Mark the modal as a centered modal.\n *\n * @method setVerticallyCentered\n */\n setVerticallyCentered() {\n if (this.isVerticallyCentered()) {\n return;\n }\n this.getModal().addClass('modal-dialog-centered');\n }\n\n /**\n * Check if the modal is a large modal.\n *\n * @method isLarge\n * @return {bool}\n */\n isLarge() {\n return this.getModal().hasClass('modal-lg');\n }\n\n /**\n * Check if the modal is vertically centered.\n *\n * @method isVerticallyCentered\n * @return {bool}\n */\n isVerticallyCentered() {\n return this.getModal().hasClass('modal-dialog-centered');\n }\n\n /**\n * Mark the modal as a small modal.\n *\n * @method setSmall\n */\n setSmall() {\n if (this.isSmall()) {\n return;\n }\n\n this.getModal().removeClass('modal-lg');\n }\n\n /**\n * Check if the modal is a small modal.\n *\n * @method isSmall\n * @return {bool}\n */\n isSmall() {\n return !this.getModal().hasClass('modal-lg');\n }\n\n /**\n * Set this modal to be scrollable or not.\n *\n * @method setScrollable\n * @param {bool} value Whether the modal is scrollable or not\n */\n setScrollable(value) {\n if (!value) {\n this.getModal()[0].classList.remove('modal-dialog-scrollable');\n return;\n }\n\n this.getModal()[0].classList.add('modal-dialog-scrollable');\n }\n\n\n /**\n * Determine the highest z-index value currently on the page.\n *\n * @method calculateZIndex\n * @return {int}\n */\n calculateZIndex() {\n const items = $(`${SELECTORS.DIALOG}, ${SELECTORS.MENU_BAR}, ${SELECTORS.HAS_Z_INDEX}`);\n let zIndex = parseInt(this.root.css('z-index'));\n\n items.each((index, item) => {\n item = $(item);\n if (!item.is(':visible')) {\n // Do not include items which are not visible in the z-index calculation.\n // This is important because some dialogues are not removed from the DOM.\n return;\n }\n // Note that webkit browsers won't return the z-index value from the CSS stylesheet\n // if the element doesn't have a position specified. Instead it'll return \"auto\".\n const itemZIndex = item.css('z-index') ? parseInt(item.css('z-index')) : 0;\n\n if (itemZIndex > zIndex) {\n zIndex = itemZIndex;\n }\n });\n\n return zIndex;\n }\n\n /**\n * Check if this modal is visible.\n *\n * @method isVisible\n * @return {bool}\n */\n isVisible() {\n return this.root.hasClass('show');\n }\n\n /**\n * Check if this modal has focus.\n *\n * @method hasFocus\n * @return {bool}\n */\n hasFocus() {\n const target = $(document.activeElement);\n return this.root.is(target) || this.root.has(target).length;\n }\n\n /**\n * Check if this modal has CSS transitions applied.\n *\n * @method hasTransitions\n * @return {bool}\n */\n hasTransitions() {\n return this.getRoot().hasClass('fade');\n }\n\n /**\n * Gets the jQuery wrapped node that the Modal should be attached to.\n *\n * @returns {jQuery}\n */\n getAttachmentPoint() {\n return $(Fullscreen.getElement() || this.attachmentPoint);\n }\n\n /**\n * Display this modal. The modal will be attached to the DOM if it hasn't\n * already been.\n *\n * @method show\n * @returns {Promise}\n */\n show() {\n if (this.isVisible()) {\n return $.Deferred().resolve();\n }\n\n const pendingPromise = new Pending('core/modal:show');\n\n if (this.hasFooterContent()) {\n this.showFooter();\n } else {\n this.hideFooter();\n }\n\n this.attachToDOM();\n\n // If the focusOnClose was not set. Set the focus back to triggered element.\n if (!this.focusOnClose && document.activeElement) {\n this.focusOnClose = document.activeElement;\n }\n\n return this.getBackdrop()\n .then((backdrop) => {\n const currentIndex = this.calculateZIndex();\n const newIndex = currentIndex + 2;\n const newBackdropIndex = newIndex - 1;\n this.root.css('z-index', newIndex);\n backdrop.setZIndex(newBackdropIndex);\n backdrop.show();\n\n this.root.removeClass('hide').addClass('show');\n this.accessibilityShow();\n this.getModal().focus();\n $('body').addClass('modal-open');\n this.root.trigger(ModalEvents.shown, this);\n\n return;\n })\n .then(pendingPromise.resolve);\n }\n\n /**\n * Hide this modal if it does not contain a form.\n *\n * @method hideIfNotForm\n */\n hideIfNotForm() {\n const formElement = this.modal.find(SELECTORS.FORM);\n if (formElement.length == 0) {\n this.hide();\n }\n }\n\n /**\n * Hide this modal.\n *\n * @method hide\n */\n hide() {\n this.getBackdrop().done((backdrop) => {\n FocusLock.untrapFocus();\n\n if (!this.countOtherVisibleModals()) {\n // Hide the backdrop if we're the last open modal.\n backdrop.hide();\n $('body').removeClass('modal-open');\n }\n\n const currentIndex = parseInt(this.root.css('z-index'));\n this.root.css('z-index', '');\n backdrop.setZIndex(currentIndex - 3);\n\n this.accessibilityHide();\n\n if (this.hasTransitions()) {\n // Wait for CSS transitions to complete before hiding the element.\n this.getRoot().one('transitionend webkitTransitionEnd oTransitionEnd', () => {\n this.getRoot().removeClass('show').addClass('hide');\n });\n } else {\n this.getRoot().removeClass('show').addClass('hide');\n }\n\n // Ensure the modal is moved onto the body node if it is still attached to the DOM.\n if ($(document.body).find(this.getRoot()).length) {\n $(document.body).append(this.getRoot());\n }\n\n this.root.trigger(ModalEvents.hidden, this);\n });\n }\n\n /**\n * Remove this modal from the DOM.\n *\n * @method destroy\n */\n destroy() {\n this.hide();\n this.root.remove();\n this.root.trigger(ModalEvents.destroyed, this);\n this.attachmentPoint.remove();\n }\n\n /**\n * Sets the appropriate aria attributes on this dialogue and the other\n * elements in the DOM to ensure that screen readers are able to navigate\n * the dialogue popup correctly.\n *\n * @method accessibilityShow\n */\n accessibilityShow() {\n // Make us visible to screen readers.\n Aria.unhide(this.root.get());\n\n // Hide siblings.\n Aria.hideSiblings(this.root.get()[0]);\n }\n\n /**\n * Restores the aria visibility on the DOM elements changed when displaying\n * the dialogue popup and makes the dialogue aria hidden to allow screen\n * readers to navigate the main page correctly when the dialogue is closed.\n *\n * @method accessibilityHide\n */\n accessibilityHide() {\n // Unhide siblings.\n Aria.unhideSiblings(this.root.get()[0]);\n\n // Hide this modal.\n Aria.hide(this.root.get());\n }\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n registerEventListeners() {\n this.getRoot().on('keydown', (e) => {\n if (!this.isVisible()) {\n return;\n }\n\n if (e.keyCode == KeyCodes.escape) {\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n\n // Listen for clicks on the modal container.\n this.getRoot().click((e) => {\n // If the click wasn't inside the modal element then we should\n // hide the modal.\n if (!$(e.target).closest(SELECTORS.MODAL).length) {\n // The check above fails to detect the click was inside the modal when the DOM tree is already changed.\n // So, we check if we can still find the container element or not. If not, then the DOM tree is changed.\n // It's best not to hide the modal in that case.\n if ($(e.target).closest(SELECTORS.CONTAINER).length) {\n const outsideClickEvent = $.Event(ModalEvents.outsideClick);\n this.getRoot().trigger(outsideClickEvent, this);\n\n if (!outsideClickEvent.isDefaultPrevented()) {\n this.hideIfNotForm();\n }\n }\n }\n });\n\n CustomEvents.define(this.getModal(), [CustomEvents.events.activate]);\n this.getModal().on(CustomEvents.events.activate, SELECTORS.HIDE, (e, data) => {\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n data.originalEvent.preventDefault();\n });\n\n this.getRoot().on(ModalEvents.hidden, () => {\n if (this.focusOnClose) {\n // Focus on the element that actually triggers the modal.\n this.focusOnClose.focus();\n }\n });\n }\n\n /**\n * Register a listener to close the dialogue when the cancel button is pressed.\n *\n * @method registerCloseOnCancel\n */\n registerCloseOnCancel() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('cancel'), (e, data) => {\n const cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n data.originalEvent.preventDefault();\n\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n }\n\n /**\n * Register a listener to close the dialogue when the save button is pressed.\n *\n * @method registerCloseOnSave\n */\n registerCloseOnSave() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('save'), (e, data) => {\n const saveEvent = $.Event(ModalEvents.save);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n data.originalEvent.preventDefault();\n\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n }\n\n\n /**\n * Register a listener to close the dialogue when the delete button is pressed.\n *\n * @method registerCloseOnDelete\n */\n registerCloseOnDelete() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('delete'), (e, data) => {\n const deleteEvent = $.Event(ModalEvents.delete);\n this.getRoot().trigger(deleteEvent, this);\n\n if (!deleteEvent.isDefaultPrevented()) {\n data.originalEvent.preventDefault();\n\n if (this.removeOnClose) {\n this.destroy();\n } else {\n this.hide();\n }\n }\n });\n }\n\n /**\n * Set or resolve and set the value using the function.\n *\n * @method asyncSet\n * @param {(string|object)} value The string or jQuery promise.\n * @param {function} setFunction The setter\n * @return {Promise}\n */\n asyncSet(value, setFunction) {\n const getWrappedValue = (value) => {\n if (value instanceof Promise) {\n return $.when(value);\n }\n\n if (typeof value !== 'object' || !value.hasOwnProperty('then')) {\n return $.Deferred().resolve(value);\n }\n\n return value;\n };\n\n return getWrappedValue(value)\n .then((content) => setFunction(content))\n .catch(Notification.exception);\n }\n\n /**\n * Set the title text of a button.\n *\n * This method is overloaded to take either a string value for the button title or a jQuery promise that is resolved with\n * text most commonly from a Str.get_string call.\n *\n * @param {DOMString} action The action of the button\n * @param {(String|object)} value The button text, or a promise which will resolve to it\n * @returns {Promise}\n */\n setButtonText(action, value) {\n const button = this.getFooter().find(this.getActionSelector(action));\n\n if (!button) {\n throw new Error(\"Unable to find the '\" + action + \"' button\");\n }\n\n return this.asyncSet(value, button.text.bind(button));\n }\n\n /**\n * Get the Selector for an action.\n *\n * @param {String} action\n * @returns {DOMString}\n */\n getActionSelector(action) {\n return \"[data-action='\" + action + \"']\";\n }\n\n /**\n * Set the flag to remove the modal from the DOM on close.\n *\n * @param {Boolean} remove\n */\n setRemoveOnClose(remove) {\n this.removeOnClose = remove;\n }\n\n /**\n * Set the return element for the modal.\n *\n * @param {Element|jQuery} element Element to focus when the modal is closed\n */\n setReturnElement(element) {\n this.focusOnClose = element;\n }\n\n /**\n * Set the a button enabled or disabled.\n *\n * @param {DOMString} action The action of the button\n * @param {Boolean} disabled the new disabled value\n */\n setButtonDisabled(action, disabled) {\n const button = this.getFooter().find(this.getActionSelector(action));\n\n if (!button) {\n throw new Error(\"Unable to find the '\" + action + \"' button\");\n }\n if (disabled) {\n button.attr('disabled', '');\n } else {\n button.removeAttr('disabled');\n }\n }\n}\n"],"names":["SELECTORS","TEMPLATES","Modal","constructor","root","modal","this","find","header","headerPromise","$","Deferred","title","titlePromise","body","bodyPromise","footer","footerPromise","hiddenSiblings","isAttached","bodyJS","footerJS","modalCount","modalCounter","attachmentPoint","document","createElement","append","focusOnClose","is","Notification","exception","message","length","registerEventListeners","TYPE","Error","TEMPLATE","ModalRegistry","register","attachToDOM","getAttachmentPoint","FocusLock","trapFocus","Templates","runTemplateJS","countOtherVisibleModals","count","each","index","element","hasClass","getBackdrop","backdropPromise","render","then","html","ModalBackdrop","catch","getRoot","getModal","getTitle","getBody","getFooter","getTitlePromise","getBodyPromise","getFooterPromise","getModalCount","setTitle","value","asyncSet","bind","resolve","setBody","FilterEvents","notifyFilterContentUpdated","trigger","ModalEvents","bodyRendered","modalPromise","Pending","contentPromise","css","when","state","height","innerHeight","animate","loadingIcon","hide","fadeIn","promise","fadeOut","js","result","isVisible","currentHeight","newHeight","opacity","duration","queue","always","setBodyContent","_ref","setFooter","showFooter","hasFooterContent","children","hideFooter","addClass","removeClass","setLarge","isLarge","setVerticallyCentered","isVerticallyCentered","setSmall","isSmall","setScrollable","classList","add","remove","calculateZIndex","items","zIndex","parseInt","item","itemZIndex","hasFocus","target","activeElement","has","hasTransitions","Fullscreen","getElement","show","pendingPromise","backdrop","newIndex","newBackdropIndex","setZIndex","accessibilityShow","focus","shown","hideIfNotForm","done","untrapFocus","currentIndex","accessibilityHide","one","hidden","destroy","destroyed","Aria","unhide","get","hideSiblings","unhideSiblings","on","e","keyCode","KeyCodes","escape","removeOnClose","click","closest","outsideClickEvent","Event","outsideClick","isDefaultPrevented","CustomEvents","define","events","activate","data","originalEvent","preventDefault","registerCloseOnCancel","getActionSelector","cancelEvent","cancel","registerCloseOnSave","saveEvent","save","registerCloseOnDelete","deleteEvent","delete","setFunction","Promise","hasOwnProperty","getWrappedValue","content","setButtonText","action","button","text","setRemoveOnClose","setReturnElement","setButtonDisabled","disabled","attr","removeAttr"],"mappings":"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"}
\ No newline at end of file
diff --git a/lib/amd/src/modal.js b/lib/amd/src/modal.js
index fa0940bdddd..54058e01a87 100644
--- a/lib/amd/src/modal.js
+++ b/lib/amd/src/modal.js
@@ -89,7 +89,7 @@ export default class Modal {
this.isAttached = false;
this.bodyJS = null;
this.footerJS = null;
- this.modalCount = this.modalCounter++;
+ this.modalCount = Modal.modalCounter++;
this.attachmentPoint = document.createElement('div');
document.body.append(this.attachmentPoint);
this.focusOnClose = null;