From a2dcfd5bf68fc1255af4e937fabb40d441154bba Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Tue, 25 Aug 2020 07:47:15 +0100 Subject: [PATCH] MDL-67513 forum: View conversations while fullscreen grading Before this change when a modal was shown and an element on the page was fullscreen the modal would be created behind it. This change ensures that the modal will be inside an element that is fullscreen so that it will be correctly displayed. --- lib/amd/build/fullscreen.min.js | 2 ++ lib/amd/build/fullscreen.min.js.map | 1 + lib/amd/build/modal.min.js | 2 +- lib/amd/build/modal.min.js.map | 2 +- lib/amd/build/modal_backdrop.min.js | 2 +- lib/amd/build/modal_backdrop.min.js.map | 2 +- lib/amd/src/fullscreen.js | 48 +++++++++++++++++++++++++ lib/amd/src/modal.js | 40 +++++++++++++++++---- lib/amd/src/modal_backdrop.js | 23 ++++++++---- 9 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 lib/amd/build/fullscreen.min.js create mode 100644 lib/amd/build/fullscreen.min.js.map create mode 100644 lib/amd/src/fullscreen.js diff --git a/lib/amd/build/fullscreen.min.js b/lib/amd/build/fullscreen.min.js new file mode 100644 index 00000000000..b227c0ae0c6 --- /dev/null +++ b/lib/amd/build/fullscreen.min.js @@ -0,0 +1,2 @@ +define ("core/fullscreen",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.getElement=void 0;a.getElement=function getElement(){var a=null;if(document.fullscreenElement){a=document.fullscreenElement}else if(document.mozFullscreenElement){a=document.mozFullscreenElement}else if(document.msFullscreenElement){a=document.msFullscreenElement}else if(document.webkitFullscreenElement){a=document.webkitFullscreenElement}return a}}); +//# sourceMappingURL=fullscreen.min.js.map diff --git a/lib/amd/build/fullscreen.min.js.map b/lib/amd/build/fullscreen.min.js.map new file mode 100644 index 00000000000..82ff7a4b024 --- /dev/null +++ b/lib/amd/build/fullscreen.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/fullscreen.js"],"names":["getElement","element","document","fullscreenElement","mozFullscreenElement","msFullscreenElement","webkitFullscreenElement"],"mappings":"iJA+B0B,QAAbA,CAAAA,UAAa,EAAM,CAC5B,GAAIC,CAAAA,CAAO,CAAG,IAAd,CACA,GAAIC,QAAQ,CAACC,iBAAb,CAAgC,CAC5BF,CAAO,CAAGC,QAAQ,CAACC,iBACtB,CAFD,IAEO,IAAID,QAAQ,CAACE,oBAAb,CAAmC,CAEtCH,CAAO,CAAGC,QAAQ,CAACE,oBACtB,CAHM,IAGA,IAAIF,QAAQ,CAACG,mBAAb,CAAkC,CAErCJ,CAAO,CAAGC,QAAQ,CAACG,mBACtB,CAHM,IAGA,IAAIH,QAAQ,CAACI,uBAAb,CAAsC,CAEzCL,CAAO,CAAGC,QAAQ,CAACI,uBACtB,CAED,MAAOL,CAAAA,CACV,C","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 * Detects if an element is fullscreen.\n *\n * @module core/fullscreen\n * @class fullscreen\n * @package core\n * @copyright 2020 University of Nottingham\n * @author Neill Magill \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Gets the element that is fullscreen or null if no element is fullscreen.\n *\n * @returns {HTMLElement}\n */\nexport const getElement = () => {\n let element = null;\n if (document.fullscreenElement) {\n element = document.fullscreenElement;\n } else if (document.mozFullscreenElement) {\n // Fallback for older Firefox.\n element = document.mozFullscreenElement;\n } else if (document.msFullscreenElement) {\n // Fallback for Edge and IE.\n element = document.msFullscreenElement;\n } else if (document.webkitFullscreenElement) {\n // Fallback for Chrome, Edge and Safari.\n element = document.webkitFullscreenElement;\n }\n\n return element;\n};\n"],"file":"fullscreen.min.js"} \ No newline at end of file diff --git a/lib/amd/build/modal.min.js b/lib/amd/build/modal.min.js index 1374a94e2d5..5aef006412e 100644 --- a/lib/amd/build/modal.min.js +++ b/lib/amd/build/modal.min.js @@ -1,2 +1,2 @@ -function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core/modal",["jquery","core/templates","core/notification","core/key_codes","core/custom_interaction_events","core/modal_backdrop","core/event","core/modal_events","core/local/aria/focuslock","core/pending","core/aria"],function(a,b,c,d,e,f,g,h,i,j,k){var l={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]",FORM:"form",MENU_BAR:"[role=menubar]",HAS_Z_INDEX:".moodle-has-zindex",CAN_RECEIVE_FOCUS:"input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]"},m={LOADING:"core/loading",BACKDROP:"core/modal_backdrop"},n,o=0,p=function(b){this.root=a(b);this.modal=this.root.find(l.MODAL);this.header=this.modal.find(l.HEADER);this.headerPromise=a.Deferred();this.title=this.header.find(l.TITLE);this.titlePromise=a.Deferred();this.body=this.modal.find(l.BODY);this.bodyPromise=a.Deferred();this.footer=this.modal.find(l.FOOTER);this.footerPromise=a.Deferred();this.hiddenSiblings=[];this.isAttached=!1;this.bodyJS=null;this.footerJS=null;this.modalCount=o++;if(!this.root.is(l.CONTAINER)){c.exception({message:"Element is not a modal container"})}if(!this.modal.length){c.exception({message:"Container does not contain a modal"})}if(!this.header.length){c.exception({message:"Modal is missing a header region"})}if(!this.title.length){c.exception({message:"Modal header is missing a title region"})}if(!this.body.length){c.exception({message:"Modal is missing a body region"})}if(!this.footer.length){c.exception({message:"Modal is missing a footer region"})}this.registerEventListeners()};p.prototype.attachToDOM=function(){if(this.isAttached){return}a("body").append(this.root);i.trapFocus(this.root[0]);if(this.bodyJS){b.runTemplateJS(this.bodyJS);this.bodyJS=null}if(this.footerJS){b.runTemplateJS(this.footerJS);this.footerJS=null}this.isAttached=!0};p.prototype.countOtherVisibleModals=function(){var b=0;a("body").find(l.CONTAINER).each(function(c,d){d=a(d);if(!this.root.is(d)&&d.hasClass("show")){b++}}.bind(this));return b};p.prototype.getBackdrop=function(){if(!n){n=b.render(m.BACKDROP,{}).then(function(b){var c=a(b);return new f(c)}).fail(c.exception)}return n};p.prototype.getRoot=function(){return this.root};p.prototype.getModal=function(){return this.modal};p.prototype.getTitle=function(){return this.title};p.prototype.getBody=function(){return this.body};p.prototype.getFooter=function(){return this.footer};p.prototype.getTitlePromise=function(){return this.titlePromise};p.prototype.getBodyPromise=function(){return this.bodyPromise};p.prototype.getFooterPromise=function(){return this.footerPromise};p.prototype.getModalCount=function(){return this.modalCount};p.prototype.setTitle=function(b){var d=this.getTitle();this.titlePromise=a.Deferred();this.asyncSet(b,d.html.bind(d)).then(function(){this.titlePromise.resolve(d)}.bind(this)).catch(c.exception)};p.prototype.setBody=function(d){this.bodyPromise=a.Deferred();var e=this.getBody();if("string"==typeof d){e.html(d);g.notifyFilterContentUpdated(e);this.getRoot().trigger(h.bodyRendered,this);this.bodyPromise.resolve(e)}else{var f="amd-modal-js-pending-id-"+this.getModalCount();M.util.js_pending(f);var i=null;e.css("overflow","hidden");d=a.when(d);if("pending"==d.state()){var j=e.innerHeight();if(100>j){j=100}e.animate({height:j+"px"},150);e.html("");i=b.render(m.LOADING,{}).then(function(b){var c=a(b).hide();e.html(c);c.fadeIn(150);return a.when(c.promise(),d)}).then(function(a){return a.fadeOut(100).promise()}).then(function(){return d})}else{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 g=e.innerHeight();e.css("height",f+"px");d=e.animate({height:g+"px",opacity:1},{duration:150,queue:!1}).promise()}else{e.html(a)}if(c){if(this.isAttached){b.runTemplateJS(c)}else{this.bodyJS=c}}return d}.bind(this)).then(function(a){g.notifyFilterContentUpdated(e);this.getRoot().trigger(h.bodyRendered,this);return a}.bind(this)).then(function(){this.bodyPromise.resolve(e)}.bind(this)).fail(c.exception).always(function(){e.css("height","");e.css("overflow","");e.css("opacity","");M.util.js_complete(f)}).fail(c.exception)}};p.prototype.setFooter=function(d){this.showFooter();this.footerPromise=a.Deferred();var e=this.getFooter();if("string"==typeof d){e.html(d);this.footerPromise.resolve(e)}else{b.render(m.LOADING,{}).then(function(a){e.html(a);return d}).then(function(a,c){e.html(a);if(c){if(this.isAttached){b.runTemplateJS(c)}else{this.footerJS=c}}return e}.bind(this)).then(function(a){this.footerPromise.resolve(a)}.bind(this)).catch(c.exception)}};p.prototype.hasFooterContent=function(){return this.getFooter().children().length?!0:!1};p.prototype.hideFooter=function(){this.getFooter().addClass("hidden")};p.prototype.showFooter=function(){this.getFooter().removeClass("hidden")};p.prototype.setLarge=function(){if(this.isLarge()){return}this.getModal().addClass("modal-lg")};p.prototype.isLarge=function(){return this.getModal().hasClass("modal-lg")};p.prototype.setSmall=function(){if(this.isSmall()){return}this.getModal().removeClass("modal-lg")};p.prototype.isSmall=function(){return!this.getModal().hasClass("modal-lg")};p.prototype.setScrollable=function(a){if(!a){this.getModal()[0].classList.remove("modal-dialog-scrollable");return}this.getModal()[0].classList.add("modal-dialog-scrollable")};p.prototype.calculateZIndex=function(){var b=a(l.DIALOG+", "+l.MENU_BAR+", "+l.HAS_Z_INDEX),c=parseInt(this.root.css("z-index"));b.each(function(b,d){d=a(d);var e=d.css("z-index")?parseInt(d.css("z-index")):0;if(e>c){c=e}});return c};p.prototype.isVisible=function(){return this.root.hasClass("show")};p.prototype.hasFocus=function(){var b=a(document.activeElement);return this.root.is(b)||this.root.has(b).length};p.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")};p.prototype.show=function(){if(this.isVisible()){return a.Deferred().resolve()}var b=new j("core/modal:show");if(this.hasFooterContent()){this.showFooter()}else{this.hideFooter()}if(!this.isAttached){this.attachToDOM()}return this.getBackdrop().then(function(b){var c=this.calculateZIndex(),d=c+2;this.root.css("z-index",d);b.setZIndex(d-1);b.show();this.root.removeClass("hide").addClass("show");this.accessibilityShow();this.getModal().focus();a("body").addClass("modal-open");this.root.trigger(h.shown,this)}.bind(this)).then(b.resolve)};p.prototype.hideIfNotForm=function(){var a=this.modal.find(l.FORM);if(0==a.length){this.hide()}};p.prototype.hide=function(){this.getBackdrop().done(function(b){i.untrapFocus();if(!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();if(this.hasTransitions()){this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",function(){this.getRoot().removeClass("show").addClass("hide")}.bind(this))}else{this.getRoot().removeClass("show").addClass("hide")}this.root.trigger(h.hidden,this)}.bind(this))};p.prototype.destroy=function(){this.hide();this.root.remove();this.root.trigger(h.destroyed,this)};p.prototype.accessibilityShow=function(){k.unhide(this.root.get());k.hideSiblings(this.root.get()[0])};p.prototype.accessibilityHide=function(){k.unhideSiblings(this.root.get()[0]);k.hide(this.root.get())};p.prototype.registerEventListeners=function(){this.getRoot().on("keydown",function(a){if(!this.isVisible()){return}if(a.keyCode==d.escape){this.hide()}}.bind(this));this.getRoot().click(function(b){if(!a(b.target).closest(l.MODAL).length){if(a(b.target).closest(l.CONTAINER).length){var c=a.Event(h.outsideClick);this.getRoot().trigger(c,this);if(!c.isDefaultPrevented()){this.hideIfNotForm()}}}}.bind(this));e.define(this.getModal(),[e.events.activate]);this.getModal().on(e.events.activate,l.HIDE,function(a,b){this.hide();b.originalEvent.preventDefault()}.bind(this))};p.prototype.registerCloseOnCancel=function(){this.getModal().on(e.events.activate,this.getActionSelector("cancel"),function(b,c){var d=a.Event(h.cancel);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){c.originalEvent.preventDefault();if(this.removeOnClose){this.destroy()}else{this.hide()}}}.bind(this))};p.prototype.registerCloseOnSave=function(){this.getModal().on(e.events.activate,this.getActionSelector("save"),function(b,c){var d=a.Event(h.save);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){c.originalEvent.preventDefault();if(this.removeOnClose){this.destroy()}else{this.hide()}}}.bind(this))};p.prototype.asyncSet=function(b,d){var e=b;if("object"!==_typeof(b)||!b.hasOwnProperty("then")){e=a.Deferred();e.resolve(b)}e.then(function(a){d(a)}).fail(c.exception);return e};p.prototype.setButtonText=function(a,b){var c=this.getFooter().find(this.getActionSelector(a));if(!c){throw new Error("Unable to find the '"+a+"' button")}return this.asyncSet(b,c.text.bind(c))};p.prototype.getActionSelector=function(a){return"[data-action='"+a+"']"};p.prototype.setRemoveOnClose=function(a){this.removeOnClose=a};return p}); +function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core/modal",["jquery","core/templates","core/notification","core/key_codes","core/custom_interaction_events","core/modal_backdrop","core/event","core/modal_events","core/local/aria/focuslock","core/pending","core/aria","core/fullscreen"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m={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]",FORM:"form",MENU_BAR:"[role=menubar]",HAS_Z_INDEX:".moodle-has-zindex",CAN_RECEIVE_FOCUS:"input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]"},n={LOADING:"core/loading",BACKDROP:"core/modal_backdrop"},o,p=0,q=function(b){this.root=a(b);this.modal=this.root.find(m.MODAL);this.header=this.modal.find(m.HEADER);this.headerPromise=a.Deferred();this.title=this.header.find(m.TITLE);this.titlePromise=a.Deferred();this.body=this.modal.find(m.BODY);this.bodyPromise=a.Deferred();this.footer=this.modal.find(m.FOOTER);this.footerPromise=a.Deferred();this.hiddenSiblings=[];this.isAttached=!1;this.bodyJS=null;this.footerJS=null;this.modalCount=p++;if(!this.root.is(m.CONTAINER)){c.exception({message:"Element is not a modal container"})}if(!this.modal.length){c.exception({message:"Container does not contain a modal"})}if(!this.header.length){c.exception({message:"Modal is missing a header region"})}if(!this.title.length){c.exception({message:"Modal header is missing a title region"})}if(!this.body.length){c.exception({message:"Modal is missing a body region"})}if(!this.footer.length){c.exception({message:"Modal is missing a footer region"})}this.registerEventListeners()};q.prototype.attachToDOM=function(){this.getAttachmentPoint().append(this.root);if(this.isAttached){return}i.trapFocus(this.root[0]);if(this.bodyJS){b.runTemplateJS(this.bodyJS);this.bodyJS=null}if(this.footerJS){b.runTemplateJS(this.footerJS);this.footerJS=null}this.isAttached=!0};q.prototype.countOtherVisibleModals=function(){var b=0;a("body").find(m.CONTAINER).each(function(c,d){d=a(d);if(!this.root.is(d)&&d.hasClass("show")){b++}}.bind(this));return b};q.prototype.getBackdrop=function(){if(!o){o=b.render(n.BACKDROP,{}).then(function(b){var c=a(b);return new f(c)}).fail(c.exception)}return o};q.prototype.getRoot=function(){return this.root};q.prototype.getModal=function(){return this.modal};q.prototype.getTitle=function(){return this.title};q.prototype.getBody=function(){return this.body};q.prototype.getFooter=function(){return this.footer};q.prototype.getTitlePromise=function(){return this.titlePromise};q.prototype.getBodyPromise=function(){return this.bodyPromise};q.prototype.getFooterPromise=function(){return this.footerPromise};q.prototype.getModalCount=function(){return this.modalCount};q.prototype.setTitle=function(b){var d=this.getTitle();this.titlePromise=a.Deferred();this.asyncSet(b,d.html.bind(d)).then(function(){this.titlePromise.resolve(d)}.bind(this)).catch(c.exception)};q.prototype.setBody=function(d){this.bodyPromise=a.Deferred();var e=this.getBody();if("string"==typeof d){e.html(d);g.notifyFilterContentUpdated(e);this.getRoot().trigger(h.bodyRendered,this);this.bodyPromise.resolve(e)}else{var f="amd-modal-js-pending-id-"+this.getModalCount();M.util.js_pending(f);var i=null;e.css("overflow","hidden");d=a.when(d);if("pending"==d.state()){var j=e.innerHeight();if(100>j){j=100}e.animate({height:j+"px"},150);e.html("");i=b.render(n.LOADING,{}).then(function(b){var c=a(b).hide();e.html(c);c.fadeIn(150);return a.when(c.promise(),d)}).then(function(a){return a.fadeOut(100).promise()}).then(function(){return d})}else{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 g=e.innerHeight();e.css("height",f+"px");d=e.animate({height:g+"px",opacity:1},{duration:150,queue:!1}).promise()}else{e.html(a)}if(c){if(this.isAttached){b.runTemplateJS(c)}else{this.bodyJS=c}}return d}.bind(this)).then(function(a){g.notifyFilterContentUpdated(e);this.getRoot().trigger(h.bodyRendered,this);return a}.bind(this)).then(function(){this.bodyPromise.resolve(e)}.bind(this)).fail(c.exception).always(function(){e.css("height","");e.css("overflow","");e.css("opacity","");M.util.js_complete(f)}).fail(c.exception)}};q.prototype.setFooter=function(d){this.showFooter();this.footerPromise=a.Deferred();var e=this.getFooter();if("string"==typeof d){e.html(d);this.footerPromise.resolve(e)}else{b.render(n.LOADING,{}).then(function(a){e.html(a);return d}).then(function(a,c){e.html(a);if(c){if(this.isAttached){b.runTemplateJS(c)}else{this.footerJS=c}}return e}.bind(this)).then(function(a){this.footerPromise.resolve(a)}.bind(this)).catch(c.exception)}};q.prototype.hasFooterContent=function(){return this.getFooter().children().length?!0:!1};q.prototype.hideFooter=function(){this.getFooter().addClass("hidden")};q.prototype.showFooter=function(){this.getFooter().removeClass("hidden")};q.prototype.setLarge=function(){if(this.isLarge()){return}this.getModal().addClass("modal-lg")};q.prototype.isLarge=function(){return this.getModal().hasClass("modal-lg")};q.prototype.setSmall=function(){if(this.isSmall()){return}this.getModal().removeClass("modal-lg")};q.prototype.isSmall=function(){return!this.getModal().hasClass("modal-lg")};q.prototype.setScrollable=function(a){if(!a){this.getModal()[0].classList.remove("modal-dialog-scrollable");return}this.getModal()[0].classList.add("modal-dialog-scrollable")};q.prototype.calculateZIndex=function(){var b=a(m.DIALOG+", "+m.MENU_BAR+", "+m.HAS_Z_INDEX),c=parseInt(this.root.css("z-index"));b.each(function(b,d){d=a(d);var e=d.css("z-index")?parseInt(d.css("z-index")):0;if(e>c){c=e}});return c};q.prototype.isVisible=function(){return this.root.hasClass("show")};q.prototype.hasFocus=function(){var b=a(document.activeElement);return this.root.is(b)||this.root.has(b).length};q.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")};q.prototype.getAttachmentPoint=function(){return a(l.getElement()||document.body)};q.prototype.show=function(){if(this.isVisible()){return a.Deferred().resolve()}var b=new j("core/modal:show");if(this.hasFooterContent()){this.showFooter()}else{this.hideFooter()}this.attachToDOM();return this.getBackdrop().then(function(b){var c=this.calculateZIndex(),d=c+2;this.root.css("z-index",d);b.setZIndex(d-1);b.show();this.root.removeClass("hide").addClass("show");this.accessibilityShow();this.getModal().focus();a("body").addClass("modal-open");this.root.trigger(h.shown,this)}.bind(this)).then(b.resolve)};q.prototype.hideIfNotForm=function(){var a=this.modal.find(m.FORM);if(0==a.length){this.hide()}};q.prototype.hide=function(){this.getBackdrop().done(function(b){i.untrapFocus();if(!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();if(this.hasTransitions()){this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",function(){this.getRoot().removeClass("show").addClass("hide")}.bind(this))}else{this.getRoot().removeClass("show").addClass("hide")}a(document.body).append(this.getRoot());this.root.trigger(h.hidden,this)}.bind(this))};q.prototype.destroy=function(){this.hide();this.root.remove();this.root.trigger(h.destroyed,this)};q.prototype.accessibilityShow=function(){k.unhide(this.root.get());k.hideSiblings(this.root.get()[0])};q.prototype.accessibilityHide=function(){k.unhideSiblings(this.root.get()[0]);k.hide(this.root.get())};q.prototype.registerEventListeners=function(){this.getRoot().on("keydown",function(a){if(!this.isVisible()){return}if(a.keyCode==d.escape){this.hide()}}.bind(this));this.getRoot().click(function(b){if(!a(b.target).closest(m.MODAL).length){if(a(b.target).closest(m.CONTAINER).length){var c=a.Event(h.outsideClick);this.getRoot().trigger(c,this);if(!c.isDefaultPrevented()){this.hideIfNotForm()}}}}.bind(this));e.define(this.getModal(),[e.events.activate]);this.getModal().on(e.events.activate,m.HIDE,function(a,b){this.hide();b.originalEvent.preventDefault()}.bind(this))};q.prototype.registerCloseOnCancel=function(){this.getModal().on(e.events.activate,this.getActionSelector("cancel"),function(b,c){var d=a.Event(h.cancel);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){c.originalEvent.preventDefault();if(this.removeOnClose){this.destroy()}else{this.hide()}}}.bind(this))};q.prototype.registerCloseOnSave=function(){this.getModal().on(e.events.activate,this.getActionSelector("save"),function(b,c){var d=a.Event(h.save);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){c.originalEvent.preventDefault();if(this.removeOnClose){this.destroy()}else{this.hide()}}}.bind(this))};q.prototype.asyncSet=function(b,d){var e=b;if("object"!==_typeof(b)||!b.hasOwnProperty("then")){e=a.Deferred();e.resolve(b)}e.then(function(a){d(a)}).fail(c.exception);return e};q.prototype.setButtonText=function(a,b){var c=this.getFooter().find(this.getActionSelector(a));if(!c){throw new Error("Unable to find the '"+a+"' button")}return this.asyncSet(b,c.text.bind(c))};q.prototype.getActionSelector=function(a){return"[data-action='"+a+"']"};q.prototype.setRemoveOnClose=function(a){this.removeOnClose=a};return q}); //# sourceMappingURL=modal.min.js.map diff --git a/lib/amd/build/modal.min.js.map b/lib/amd/build/modal.min.js.map index 3b050c2d259..11c184f4a30 100644 --- a/lib/amd/build/modal.min.js.map +++ b/lib/amd/build/modal.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/modal.js"],"names":["define","$","Templates","Notification","KeyCodes","CustomEvents","ModalBackdrop","Event","ModalEvents","FocusLock","Pending","Aria","SELECTORS","CONTAINER","MODAL","HEADER","TITLE","BODY","FOOTER","HIDE","DIALOG","FORM","MENU_BAR","HAS_Z_INDEX","CAN_RECEIVE_FOCUS","TEMPLATES","LOADING","BACKDROP","backdropPromise","modalCounter","Modal","root","modal","find","header","headerPromise","Deferred","title","titlePromise","body","bodyPromise","footer","footerPromise","hiddenSiblings","isAttached","bodyJS","footerJS","modalCount","is","exception","message","length","registerEventListeners","prototype","attachToDOM","append","trapFocus","runTemplateJS","countOtherVisibleModals","count","each","index","element","hasClass","bind","getBackdrop","render","then","html","fail","getRoot","getModal","getTitle","getBody","getFooter","getTitlePromise","getBodyPromise","getFooterPromise","getModalCount","setTitle","value","asyncSet","resolve","catch","setBody","notifyFilterContentUpdated","trigger","bodyRendered","jsPendingId","M","util","js_pending","contentPromise","css","when","state","height","innerHeight","animate","loadingIcon","hide","fadeIn","promise","fadeOut","js","result","isVisible","currentHeight","newHeight","opacity","duration","queue","always","js_complete","setFooter","showFooter","hasFooterContent","children","hideFooter","addClass","removeClass","setLarge","isLarge","setSmall","isSmall","setScrollable","classList","remove","add","calculateZIndex","items","zIndex","parseInt","item","itemZIndex","hasFocus","target","document","activeElement","has","hasTransitions","show","pendingPromise","backdrop","currentIndex","newIndex","setZIndex","accessibilityShow","focus","shown","hideIfNotForm","formElement","done","untrapFocus","accessibilityHide","one","hidden","destroy","destroyed","unhide","get","hideSiblings","unhideSiblings","on","e","keyCode","escape","click","closest","outsideClickEvent","outsideClick","isDefaultPrevented","events","activate","data","originalEvent","preventDefault","registerCloseOnCancel","getActionSelector","cancelEvent","cancel","removeOnClose","registerCloseOnSave","saveEvent","save","setFunction","p","hasOwnProperty","content","setButtonText","action","button","Error","text","setRemoveOnClose"],"mappings":"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","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 * @class modal\n * @package core\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core/key_codes',\n 'core/custom_interaction_events',\n 'core/modal_backdrop',\n 'core/event',\n 'core/modal_events',\n 'core/local/aria/focuslock',\n 'core/pending',\n 'core/aria',\n], function($, Templates, Notification, KeyCodes, CustomEvents, ModalBackdrop, Event, ModalEvents, FocusLock, Pending, Aria) {\n\n var 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\n var TEMPLATES = {\n LOADING: 'core/loading',\n BACKDROP: 'core/modal_backdrop',\n };\n\n /**\n * Module singleton for the backdrop to be reused by all Modal instances.\n */\n var backdropPromise;\n\n /**\n * A counter that gets incremented for each modal created. This can be\n * used to generate unique values for the modals.\n */\n var modalCounter = 0;\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var Modal = function(root) {\n this.root = $(root);\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 = modalCounter++;\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 * Add the modal to the page, if it hasn't already been added. This includes running any\n * javascript that has been cached until now.\n *\n * @method attachToDOM\n */\n Modal.prototype.attachToDOM = function() {\n if (this.isAttached) {\n return;\n }\n\n $('body').append(this.root);\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 Modal.prototype.countOtherVisibleModals = function() {\n var count = 0;\n $('body').find(SELECTORS.CONTAINER).each(function(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 }.bind(this));\n\n return count;\n };\n\n /**\n * Get the modal backdrop.\n *\n * @method getBackdrop\n * @return {object} jQuery promise\n */\n Modal.prototype.getBackdrop = function() {\n if (!backdropPromise) {\n backdropPromise = Templates.render(TEMPLATES.BACKDROP, {})\n .then(function(html) {\n var element = $(html);\n\n return new ModalBackdrop(element);\n })\n .fail(Notification.exception);\n }\n\n return backdropPromise;\n };\n\n /**\n * Get the root element of this modal.\n *\n * @method getRoot\n * @return {object} jQuery object\n */\n Modal.prototype.getRoot = function() {\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 Modal.prototype.getModal = function() {\n return this.modal;\n };\n\n /**\n * Get the modal title element.\n *\n * @method getTitle\n * @return {object} jQuery object\n */\n Modal.prototype.getTitle = function() {\n return this.title;\n };\n\n /**\n * Get the modal body element.\n *\n * @method getBody\n * @return {object} jQuery object\n */\n Modal.prototype.getBody = function() {\n return this.body;\n };\n\n /**\n * Get the modal footer element.\n *\n * @method getFooter\n * @return {object} jQuery object\n */\n Modal.prototype.getFooter = function() {\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 Modal.prototype.getTitlePromise = function() {\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 Modal.prototype.getBodyPromise = function() {\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 Modal.prototype.getFooterPromise = function() {\n return this.footerPromise;\n };\n\n /**\n * Get the unique modal count.\n *\n * @method getModalCount\n * @return {int}\n */\n Modal.prototype.getModalCount = function() {\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 Modal.prototype.setTitle = function(value) {\n var title = this.getTitle();\n this.titlePromise = $.Deferred();\n\n this.asyncSet(value, title.html.bind(title))\n .then(function() {\n this.titlePromise.resolve(title);\n }.bind(this))\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 */\n Modal.prototype.setBody = function(value) {\n this.bodyPromise = $.Deferred();\n\n var body = this.getBody();\n\n if (typeof value === 'string') {\n // Just set the value if it's a string.\n body.html(value);\n Event.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n this.bodyPromise.resolve(body);\n } else {\n var jsPendingId = 'amd-modal-js-pending-id-' + this.getModalCount();\n M.util.js_pending(jsPendingId);\n // Otherwise we assume it's a promise to be resolved with\n // html and javascript.\n var 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 var 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(function(html) {\n var 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(function(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(function() {\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(function(html, js) {\n var 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 var 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 var 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 }.bind(this))\n .then(function(result) {\n Event.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n return result;\n }.bind(this))\n .then(function() {\n this.bodyPromise.resolve(body);\n return;\n }.bind(this))\n .fail(Notification.exception)\n .always(function() {\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 M.util.js_complete(jsPendingId);\n\n return;\n })\n .fail(Notification.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 Modal.prototype.setFooter = function(value) {\n // Make sure the footer is visible.\n this.showFooter();\n this.footerPromise = $.Deferred();\n\n var 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(function(html) {\n footer.html(html);\n\n return value;\n })\n .then(function(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 }.bind(this))\n .then(function(footer) {\n this.footerPromise.resolve(footer);\n return;\n }.bind(this))\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 Modal.prototype.hasFooterContent = function() {\n return this.getFooter().children().length ? true : false;\n };\n\n /**\n * Hide the footer element.\n *\n * @method hideFooter\n */\n Modal.prototype.hideFooter = function() {\n this.getFooter().addClass('hidden');\n };\n\n /**\n * Show the footer element.\n *\n * @method showFooter\n */\n Modal.prototype.showFooter = function() {\n this.getFooter().removeClass('hidden');\n };\n\n /**\n * Mark the modal as a large modal.\n *\n * @method setLarge\n */\n Modal.prototype.setLarge = function() {\n if (this.isLarge()) {\n return;\n }\n\n this.getModal().addClass('modal-lg');\n };\n\n /**\n * Check if the modal is a large modal.\n *\n * @method isLarge\n * @return {bool}\n */\n Modal.prototype.isLarge = function() {\n return this.getModal().hasClass('modal-lg');\n };\n\n /**\n * Mark the modal as a small modal.\n *\n * @method setSmall\n */\n Modal.prototype.setSmall = function() {\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 Modal.prototype.isSmall = function() {\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 Modal.prototype.setScrollable = function(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 Modal.prototype.calculateZIndex = function() {\n var items = $(SELECTORS.DIALOG + ', ' + SELECTORS.MENU_BAR + ', ' + SELECTORS.HAS_Z_INDEX);\n var zIndex = parseInt(this.root.css('z-index'));\n\n items.each(function(index, item) {\n item = $(item);\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 var 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 Modal.prototype.isVisible = function() {\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 Modal.prototype.hasFocus = function() {\n var 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 Modal.prototype.hasTransitions = function() {\n return this.getRoot().hasClass('fade');\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 Modal.prototype.show = function() {\n if (this.isVisible()) {\n return $.Deferred().resolve();\n }\n\n var pendingPromise = new Pending('core/modal:show');\n\n if (this.hasFooterContent()) {\n this.showFooter();\n } else {\n this.hideFooter();\n }\n\n if (!this.isAttached) {\n this.attachToDOM();\n }\n\n return this.getBackdrop()\n .then(function(backdrop) {\n var currentIndex = this.calculateZIndex();\n var newIndex = currentIndex + 2;\n var 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 }.bind(this))\n .then(pendingPromise.resolve);\n };\n\n /**\n * Hide this modal if it does not contain a form.\n *\n * @method hideIfNotForm\n */\n Modal.prototype.hideIfNotForm = function() {\n var 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 Modal.prototype.hide = function() {\n this.getBackdrop().done(function(backdrop) {\n FocusLock.untrapFocus();\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 var 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', function() {\n this.getRoot().removeClass('show').addClass('hide');\n }.bind(this));\n } else {\n this.getRoot().removeClass('show').addClass('hide');\n }\n\n this.root.trigger(ModalEvents.hidden, this);\n }.bind(this));\n };\n\n /**\n * Remove this modal from the DOM.\n *\n * @method destroy\n */\n Modal.prototype.destroy = function() {\n this.hide();\n this.root.remove();\n this.root.trigger(ModalEvents.destroyed, this);\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 Modal.prototype.accessibilityShow = function() {\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 Modal.prototype.accessibilityHide = function() {\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 Modal.prototype.registerEventListeners = function() {\n this.getRoot().on('keydown', function(e) {\n if (!this.isVisible()) {\n return;\n }\n\n if (e.keyCode == KeyCodes.escape) {\n this.hide();\n }\n }.bind(this));\n\n // Listen for clicks on the modal container.\n this.getRoot().click(function(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 var outsideClickEvent = $.Event(ModalEvents.outsideClick);\n this.getRoot().trigger(outsideClickEvent, this);\n\n if (!outsideClickEvent.isDefaultPrevented()) {\n this.hideIfNotForm();\n }\n }\n }\n }.bind(this));\n\n CustomEvents.define(this.getModal(), [CustomEvents.events.activate]);\n this.getModal().on(CustomEvents.events.activate, SELECTORS.HIDE, function(e, data) {\n this.hide();\n data.originalEvent.preventDefault();\n }.bind(this));\n };\n\n /**\n * Register a listener to close the dialogue when the cancel button is pressed.\n *\n * @method registerCloseOnCancel\n */\n Modal.prototype.registerCloseOnCancel = function() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('cancel'), function(e, data) {\n var 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 }.bind(this));\n };\n\n /**\n * Register a listener to close the dialogue when the save button is pressed.\n *\n * @method registerCloseOnSave\n */\n Modal.prototype.registerCloseOnSave = function() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('save'), function(e, data) {\n var 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 }.bind(this));\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 Modal.prototype.asyncSet = function(value, setFunction) {\n var p = value;\n if (typeof value !== 'object' || !value.hasOwnProperty('then')) {\n p = $.Deferred();\n p.resolve(value);\n }\n\n p.then(function(content) {\n setFunction(content);\n\n return;\n })\n .fail(Notification.exception);\n\n return p;\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 Modal.prototype.setButtonText = function(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 Modal.prototype.getActionSelector = function(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 Modal.prototype.setRemoveOnClose = function(remove) {\n this.removeOnClose = remove;\n };\n\n return Modal;\n});\n"],"file":"modal.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/modal.js"],"names":["define","$","Templates","Notification","KeyCodes","CustomEvents","ModalBackdrop","Event","ModalEvents","FocusLock","Pending","Aria","Fullscreen","SELECTORS","CONTAINER","MODAL","HEADER","TITLE","BODY","FOOTER","HIDE","DIALOG","FORM","MENU_BAR","HAS_Z_INDEX","CAN_RECEIVE_FOCUS","TEMPLATES","LOADING","BACKDROP","backdropPromise","modalCounter","Modal","root","modal","find","header","headerPromise","Deferred","title","titlePromise","body","bodyPromise","footer","footerPromise","hiddenSiblings","isAttached","bodyJS","footerJS","modalCount","is","exception","message","length","registerEventListeners","prototype","attachToDOM","getAttachmentPoint","append","trapFocus","runTemplateJS","countOtherVisibleModals","count","each","index","element","hasClass","bind","getBackdrop","render","then","html","fail","getRoot","getModal","getTitle","getBody","getFooter","getTitlePromise","getBodyPromise","getFooterPromise","getModalCount","setTitle","value","asyncSet","resolve","catch","setBody","notifyFilterContentUpdated","trigger","bodyRendered","jsPendingId","M","util","js_pending","contentPromise","css","when","state","height","innerHeight","animate","loadingIcon","hide","fadeIn","promise","fadeOut","js","result","isVisible","currentHeight","newHeight","opacity","duration","queue","always","js_complete","setFooter","showFooter","hasFooterContent","children","hideFooter","addClass","removeClass","setLarge","isLarge","setSmall","isSmall","setScrollable","classList","remove","add","calculateZIndex","items","zIndex","parseInt","item","itemZIndex","hasFocus","target","document","activeElement","has","hasTransitions","getElement","show","pendingPromise","backdrop","currentIndex","newIndex","setZIndex","accessibilityShow","focus","shown","hideIfNotForm","formElement","done","untrapFocus","accessibilityHide","one","hidden","destroy","destroyed","unhide","get","hideSiblings","unhideSiblings","on","e","keyCode","escape","click","closest","outsideClickEvent","outsideClick","isDefaultPrevented","events","activate","data","originalEvent","preventDefault","registerCloseOnCancel","getActionSelector","cancelEvent","cancel","removeOnClose","registerCloseOnSave","saveEvent","save","setFunction","p","hasOwnProperty","content","setButtonText","action","button","Error","text","setRemoveOnClose"],"mappings":"mSAwBAA,OAAM,cAAC,CACH,QADG,CAEH,gBAFG,CAGH,mBAHG,CAIH,gBAJG,CAKH,gCALG,CAMH,qBANG,CAOH,YAPG,CAQH,mBARG,CASH,2BATG,CAUH,cAVG,CAWH,WAXG,CAYH,iBAZG,CAAD,CAaH,SACCC,CADD,CAECC,CAFD,CAGCC,CAHD,CAICC,CAJD,CAKCC,CALD,CAMCC,CAND,CAOCC,CAPD,CAQCC,CARD,CASCC,CATD,CAUCC,CAVD,CAWCC,CAXD,CAYCC,CAZD,CAaD,IAEMC,CAAAA,CAAS,CAAG,CACZC,SAAS,CAAE,mCADC,CAEZC,KAAK,CAAE,yBAFK,CAGZC,MAAM,CAAE,0BAHI,CAIZC,KAAK,CAAE,yBAJK,CAKZC,IAAI,CAAE,wBALM,CAMZC,MAAM,CAAE,0BANI,CAOZC,IAAI,CAAE,wBAPM,CAQZC,MAAM,CAAE,eARI,CASZC,IAAI,CAAE,MATM,CAUZC,QAAQ,CAAE,gBAVE,CAWZC,WAAW,CAAE,oBAXD,CAYZC,iBAAiB,CAAE,6EAZP,CAFlB,CAiBMC,CAAS,CAAG,CACZC,OAAO,CAAE,cADG,CAEZC,QAAQ,CAAE,qBAFE,CAjBlB,CAyBMC,CAzBN,CA+BMC,CAAY,CAAG,CA/BrB,CAsCMC,CAAK,CAAG,SAASC,CAAT,CAAe,CACvB,KAAKA,IAAL,CAAY/B,CAAC,CAAC+B,CAAD,CAAb,CACA,KAAKC,KAAL,CAAa,KAAKD,IAAL,CAAUE,IAAV,CAAerB,CAAS,CAACE,KAAzB,CAAb,CACA,KAAKoB,MAAL,CAAc,KAAKF,KAAL,CAAWC,IAAX,CAAgBrB,CAAS,CAACG,MAA1B,CAAd,CACA,KAAKoB,aAAL,CAAqBnC,CAAC,CAACoC,QAAF,EAArB,CACA,KAAKC,KAAL,CAAa,KAAKH,MAAL,CAAYD,IAAZ,CAAiBrB,CAAS,CAACI,KAA3B,CAAb,CACA,KAAKsB,YAAL,CAAoBtC,CAAC,CAACoC,QAAF,EAApB,CACA,KAAKG,IAAL,CAAY,KAAKP,KAAL,CAAWC,IAAX,CAAgBrB,CAAS,CAACK,IAA1B,CAAZ,CACA,KAAKuB,WAAL,CAAmBxC,CAAC,CAACoC,QAAF,EAAnB,CACA,KAAKK,MAAL,CAAc,KAAKT,KAAL,CAAWC,IAAX,CAAgBrB,CAAS,CAACM,MAA1B,CAAd,CACA,KAAKwB,aAAL,CAAqB1C,CAAC,CAACoC,QAAF,EAArB,CACA,KAAKO,cAAL,CAAsB,EAAtB,CACA,KAAKC,UAAL,IACA,KAAKC,MAAL,CAAc,IAAd,CACA,KAAKC,QAAL,CAAgB,IAAhB,CACA,KAAKC,UAAL,CAAkBlB,CAAY,EAA9B,CAEA,GAAI,CAAC,KAAKE,IAAL,CAAUiB,EAAV,CAAapC,CAAS,CAACC,SAAvB,CAAL,CAAwC,CACpCX,CAAY,CAAC+C,SAAb,CAAuB,CAACC,OAAO,CAAE,kCAAV,CAAvB,CACH,CAED,GAAI,CAAC,KAAKlB,KAAL,CAAWmB,MAAhB,CAAwB,CACpBjD,CAAY,CAAC+C,SAAb,CAAuB,CAACC,OAAO,CAAE,oCAAV,CAAvB,CACH,CAED,GAAI,CAAC,KAAKhB,MAAL,CAAYiB,MAAjB,CAAyB,CACrBjD,CAAY,CAAC+C,SAAb,CAAuB,CAACC,OAAO,CAAE,kCAAV,CAAvB,CACH,CAED,GAAI,CAAC,KAAKb,KAAL,CAAWc,MAAhB,CAAwB,CACpBjD,CAAY,CAAC+C,SAAb,CAAuB,CAACC,OAAO,CAAE,wCAAV,CAAvB,CACH,CAED,GAAI,CAAC,KAAKX,IAAL,CAAUY,MAAf,CAAuB,CACnBjD,CAAY,CAAC+C,SAAb,CAAuB,CAACC,OAAO,CAAE,gCAAV,CAAvB,CACH,CAED,GAAI,CAAC,KAAKT,MAAL,CAAYU,MAAjB,CAAyB,CACrBjD,CAAY,CAAC+C,SAAb,CAAuB,CAACC,OAAO,CAAE,kCAAV,CAAvB,CACH,CAED,KAAKE,sBAAL,EACH,CAhFH,CA0FEtB,CAAK,CAACuB,SAAN,CAAgBC,WAAhB,CAA8B,UAAW,CACrC,KAAKC,kBAAL,GAA0BC,MAA1B,CAAiC,KAAKzB,IAAtC,EAEA,GAAI,KAAKa,UAAT,CAAqB,CACjB,MACH,CAEDpC,CAAS,CAACiD,SAAV,CAAoB,KAAK1B,IAAL,CAAU,CAAV,CAApB,EAIA,GAAI,KAAKc,MAAT,CAAiB,CACb5C,CAAS,CAACyD,aAAV,CAAwB,KAAKb,MAA7B,EACA,KAAKA,MAAL,CAAc,IACjB,CAED,GAAI,KAAKC,QAAT,CAAmB,CACf7C,CAAS,CAACyD,aAAV,CAAwB,KAAKZ,QAA7B,EACA,KAAKA,QAAL,CAAgB,IACnB,CAED,KAAKF,UAAL,GACH,CAtBD,CA8BAd,CAAK,CAACuB,SAAN,CAAgBM,uBAAhB,CAA0C,UAAW,CACjD,GAAIC,CAAAA,CAAK,CAAG,CAAZ,CACA5D,CAAC,CAAC,MAAD,CAAD,CAAUiC,IAAV,CAAerB,CAAS,CAACC,SAAzB,EAAoCgD,IAApC,CAAyC,SAASC,CAAT,CAAgBC,CAAhB,CAAyB,CAC9DA,CAAO,CAAG/D,CAAC,CAAC+D,CAAD,CAAX,CAGA,GAAI,CAAC,KAAKhC,IAAL,CAAUiB,EAAV,CAAae,CAAb,CAAD,EAA0BA,CAAO,CAACC,QAAR,CAAiB,MAAjB,CAA9B,CAAwD,CACpDJ,CAAK,EACR,CACJ,CAPwC,CAOvCK,IAPuC,CAOlC,IAPkC,CAAzC,EASA,MAAOL,CAAAA,CACV,CAZD,CAoBA9B,CAAK,CAACuB,SAAN,CAAgBa,WAAhB,CAA8B,UAAW,CACrC,GAAI,CAACtC,CAAL,CAAsB,CAClBA,CAAe,CAAG3B,CAAS,CAACkE,MAAV,CAAiB1C,CAAS,CAACE,QAA3B,CAAqC,EAArC,EACbyC,IADa,CACR,SAASC,CAAT,CAAe,CACjB,GAAIN,CAAAA,CAAO,CAAG/D,CAAC,CAACqE,CAAD,CAAf,CAEA,MAAO,IAAIhE,CAAAA,CAAJ,CAAkB0D,CAAlB,CACV,CALa,EAMbO,IANa,CAMRpE,CAAY,CAAC+C,SANL,CAOrB,CAED,MAAOrB,CAAAA,CACV,CAZD,CAoBAE,CAAK,CAACuB,SAAN,CAAgBkB,OAAhB,CAA0B,UAAW,CACjC,MAAO,MAAKxC,IACf,CAFD,CAUAD,CAAK,CAACuB,SAAN,CAAgBmB,QAAhB,CAA2B,UAAW,CAClC,MAAO,MAAKxC,KACf,CAFD,CAUAF,CAAK,CAACuB,SAAN,CAAgBoB,QAAhB,CAA2B,UAAW,CAClC,MAAO,MAAKpC,KACf,CAFD,CAUAP,CAAK,CAACuB,SAAN,CAAgBqB,OAAhB,CAA0B,UAAW,CACjC,MAAO,MAAKnC,IACf,CAFD,CAUAT,CAAK,CAACuB,SAAN,CAAgBsB,SAAhB,CAA4B,UAAW,CACnC,MAAO,MAAKlC,MACf,CAFD,CAUAX,CAAK,CAACuB,SAAN,CAAgBuB,eAAhB,CAAkC,UAAW,CACzC,MAAO,MAAKtC,YACf,CAFD,CAUAR,CAAK,CAACuB,SAAN,CAAgBwB,cAAhB,CAAiC,UAAW,CACxC,MAAO,MAAKrC,WACf,CAFD,CAUAV,CAAK,CAACuB,SAAN,CAAgByB,gBAAhB,CAAmC,UAAW,CAC1C,MAAO,MAAKpC,aACf,CAFD,CAUAZ,CAAK,CAACuB,SAAN,CAAgB0B,aAAhB,CAAgC,UAAW,CACvC,MAAO,MAAKhC,UACf,CAFD,CAaAjB,CAAK,CAACuB,SAAN,CAAgB2B,QAAhB,CAA2B,SAASC,CAAT,CAAgB,CACvC,GAAI5C,CAAAA,CAAK,CAAG,KAAKoC,QAAL,EAAZ,CACA,KAAKnC,YAAL,CAAoBtC,CAAC,CAACoC,QAAF,EAApB,CAEA,KAAK8C,QAAL,CAAcD,CAAd,CAAqB5C,CAAK,CAACgC,IAAN,CAAWJ,IAAX,CAAgB5B,CAAhB,CAArB,EACC+B,IADD,CACM,UAAW,CACb,KAAK9B,YAAL,CAAkB6C,OAAlB,CAA0B9C,CAA1B,CACH,CAFK,CAEJ4B,IAFI,CAEC,IAFD,CADN,EAICmB,KAJD,CAIOlF,CAAY,CAAC+C,SAJpB,CAKH,CATD,CAoBAnB,CAAK,CAACuB,SAAN,CAAgBgC,OAAhB,CAA0B,SAASJ,CAAT,CAAgB,CACtC,KAAKzC,WAAL,CAAmBxC,CAAC,CAACoC,QAAF,EAAnB,CAEA,GAAIG,CAAAA,CAAI,CAAG,KAAKmC,OAAL,EAAX,CAEA,GAAqB,QAAjB,QAAOO,CAAAA,CAAX,CAA+B,CAE3B1C,CAAI,CAAC8B,IAAL,CAAUY,CAAV,EACA3E,CAAK,CAACgF,0BAAN,CAAiC/C,CAAjC,EACA,KAAKgC,OAAL,GAAegB,OAAf,CAAuBhF,CAAW,CAACiF,YAAnC,CAAiD,IAAjD,EACA,KAAKhD,WAAL,CAAiB2C,OAAjB,CAAyB5C,CAAzB,CACH,CAND,IAMO,CACH,GAAIkD,CAAAA,CAAW,CAAG,2BAA6B,KAAKV,aAAL,EAA/C,CACAW,CAAC,CAACC,IAAF,CAAOC,UAAP,CAAkBH,CAAlB,EAGA,GAAII,CAAAA,CAAc,CAAG,IAArB,CACAtD,CAAI,CAACuD,GAAL,CAAS,UAAT,CAAqB,QAArB,EAGAb,CAAK,CAAGjF,CAAC,CAAC+F,IAAF,CAAOd,CAAP,CAAR,CAEA,GAAqB,SAAjB,EAAAA,CAAK,CAACe,KAAN,EAAJ,CAAgC,CAG5B,GAAIC,CAAAA,CAAM,CAAG1D,CAAI,CAAC2D,WAAL,EAAb,CACA,GAAa,GAAT,CAAAD,CAAJ,CAAkB,CACdA,CAAM,CAAG,GACZ,CAED1D,CAAI,CAAC4D,OAAL,CAAa,CAACF,MAAM,CAAEA,CAAM,CAAG,IAAlB,CAAb,CAAsC,GAAtC,EAEA1D,CAAI,CAAC8B,IAAL,CAAU,EAAV,EACAwB,CAAc,CAAG5F,CAAS,CAACkE,MAAV,CAAiB1C,CAAS,CAACC,OAA3B,CAAoC,EAApC,EACZ0C,IADY,CACP,SAASC,CAAT,CAAe,CACjB,GAAI+B,CAAAA,CAAW,CAAGpG,CAAC,CAACqE,CAAD,CAAD,CAAQgC,IAAR,EAAlB,CACA9D,CAAI,CAAC8B,IAAL,CAAU+B,CAAV,EACAA,CAAW,CAACE,MAAZ,CAAmB,GAAnB,EAKA,MAAOtG,CAAAA,CAAC,CAAC+F,IAAF,CAAOK,CAAW,CAACG,OAAZ,EAAP,CAA8BtB,CAA9B,CACV,CAVY,EAWZb,IAXY,CAWP,SAASgC,CAAT,CAAsB,CAIxB,MAAOA,CAAAA,CAAW,CAACI,OAAZ,CAAoB,GAApB,EAAyBD,OAAzB,EACV,CAhBY,EAiBZnC,IAjBY,CAiBP,UAAW,CACb,MAAOa,CAAAA,CACV,CAnBY,CAoBpB,CA/BD,IA+BO,CAGHY,CAAc,CAAGZ,CACpB,CAGDY,CAAc,CAACzB,IAAf,CAAoB,SAASC,CAAT,CAAeoC,CAAf,CAAmB,CACnC,GAAIC,CAAAA,CAAM,CAAG,IAAb,CAEA,GAAI,KAAKC,SAAL,EAAJ,CAAsB,CAGlBpE,CAAI,CAACuD,GAAL,CAAS,SAAT,CAAoB,CAApB,EACA,GAAIc,CAAAA,CAAa,CAAGrE,CAAI,CAAC2D,WAAL,EAApB,CACA3D,CAAI,CAAC8B,IAAL,CAAUA,CAAV,EAKA9B,CAAI,CAACuD,GAAL,CAAS,QAAT,CAAmB,EAAnB,EACA,GAAIe,CAAAA,CAAS,CAAGtE,CAAI,CAAC2D,WAAL,EAAhB,CACA3D,CAAI,CAACuD,GAAL,CAAS,QAAT,CAAmBc,CAAa,CAAG,IAAnC,EACAF,CAAM,CAAGnE,CAAI,CAAC4D,OAAL,CACL,CAACF,MAAM,CAAEY,CAAS,CAAG,IAArB,CAA2BC,OAAO,CAAE,CAApC,CADK,CAEL,CAACC,QAAQ,CAAE,GAAX,CAAgBC,KAAK,GAArB,CAFK,EAGPT,OAHO,EAIZ,CAjBD,IAiBO,CAGHhE,CAAI,CAAC8B,IAAL,CAAUA,CAAV,CACH,CAED,GAAIoC,CAAJ,CAAQ,CACJ,GAAI,KAAK7D,UAAT,CAAqB,CAEjB3C,CAAS,CAACyD,aAAV,CAAwB+C,CAAxB,CACH,CAHD,IAGO,CAEH,KAAK5D,MAAL,CAAc4D,CACjB,CACJ,CAED,MAAOC,CAAAA,CACV,CArCmB,CAqClBzC,IArCkB,CAqCb,IArCa,CAApB,EAsCCG,IAtCD,CAsCM,SAASsC,CAAT,CAAiB,CACnBpG,CAAK,CAACgF,0BAAN,CAAiC/C,CAAjC,EACA,KAAKgC,OAAL,GAAegB,OAAf,CAAuBhF,CAAW,CAACiF,YAAnC,CAAiD,IAAjD,EACA,MAAOkB,CAAAA,CACV,CAJK,CAIJzC,IAJI,CAIC,IAJD,CAtCN,EA2CCG,IA3CD,CA2CM,UAAW,CACb,KAAK5B,WAAL,CAAiB2C,OAAjB,CAAyB5C,CAAzB,CAEH,CAHK,CAGJ0B,IAHI,CAGC,IAHD,CA3CN,EA+CCK,IA/CD,CA+CMpE,CAAY,CAAC+C,SA/CnB,EAgDCgE,MAhDD,CAgDQ,UAAW,CAGf1E,CAAI,CAACuD,GAAL,CAAS,QAAT,CAAmB,EAAnB,EACAvD,CAAI,CAACuD,GAAL,CAAS,UAAT,CAAqB,EAArB,EACAvD,CAAI,CAACuD,GAAL,CAAS,SAAT,CAAoB,EAApB,EACAJ,CAAC,CAACC,IAAF,CAAOuB,WAAP,CAAmBzB,CAAnB,CAGH,CAzDD,EA0DCnB,IA1DD,CA0DMpE,CAAY,CAAC+C,SA1DnB,CA2DH,CACJ,CAxHD,CAqIAnB,CAAK,CAACuB,SAAN,CAAgB8D,SAAhB,CAA4B,SAASlC,CAAT,CAAgB,CAExC,KAAKmC,UAAL,GACA,KAAK1E,aAAL,CAAqB1C,CAAC,CAACoC,QAAF,EAArB,CAEA,GAAIK,CAAAA,CAAM,CAAG,KAAKkC,SAAL,EAAb,CAEA,GAAqB,QAAjB,QAAOM,CAAAA,CAAX,CAA+B,CAE3BxC,CAAM,CAAC4B,IAAP,CAAYY,CAAZ,EACA,KAAKvC,aAAL,CAAmByC,OAAnB,CAA2B1C,CAA3B,CACH,CAJD,IAIO,CAGHxC,CAAS,CAACkE,MAAV,CAAiB1C,CAAS,CAACC,OAA3B,CAAoC,EAApC,EACC0C,IADD,CACM,SAASC,CAAT,CAAe,CACjB5B,CAAM,CAAC4B,IAAP,CAAYA,CAAZ,EAEA,MAAOY,CAAAA,CACV,CALD,EAMCb,IAND,CAMM,SAASC,CAAT,CAAeoC,CAAf,CAAmB,CACrBhE,CAAM,CAAC4B,IAAP,CAAYA,CAAZ,EAEA,GAAIoC,CAAJ,CAAQ,CACJ,GAAI,KAAK7D,UAAT,CAAqB,CAEjB3C,CAAS,CAACyD,aAAV,CAAwB+C,CAAxB,CACH,CAHD,IAGO,CAEH,KAAK3D,QAAL,CAAgB2D,CACnB,CACJ,CAED,MAAOhE,CAAAA,CACV,CAdK,CAcJwB,IAdI,CAcC,IAdD,CANN,EAqBCG,IArBD,CAqBM,SAAS3B,CAAT,CAAiB,CACnB,KAAKC,aAAL,CAAmByC,OAAnB,CAA2B1C,CAA3B,CAEH,CAHK,CAGJwB,IAHI,CAGC,IAHD,CArBN,EAyBCmB,KAzBD,CAyBOlF,CAAY,CAAC+C,SAzBpB,CA0BH,CACJ,CAzCD,CAiDAnB,CAAK,CAACuB,SAAN,CAAgBgE,gBAAhB,CAAmC,UAAW,CAC1C,MAAO,MAAK1C,SAAL,GAAiB2C,QAAjB,GAA4BnE,MAA5B,MACV,CAFD,CASArB,CAAK,CAACuB,SAAN,CAAgBkE,UAAhB,CAA6B,UAAW,CACpC,KAAK5C,SAAL,GAAiB6C,QAAjB,CAA0B,QAA1B,CACH,CAFD,CASA1F,CAAK,CAACuB,SAAN,CAAgB+D,UAAhB,CAA6B,UAAW,CACpC,KAAKzC,SAAL,GAAiB8C,WAAjB,CAA6B,QAA7B,CACH,CAFD,CASA3F,CAAK,CAACuB,SAAN,CAAgBqE,QAAhB,CAA2B,UAAW,CAClC,GAAI,KAAKC,OAAL,EAAJ,CAAoB,CAChB,MACH,CAED,KAAKnD,QAAL,GAAgBgD,QAAhB,CAAyB,UAAzB,CACH,CAND,CAcA1F,CAAK,CAACuB,SAAN,CAAgBsE,OAAhB,CAA0B,UAAW,CACjC,MAAO,MAAKnD,QAAL,GAAgBR,QAAhB,CAAyB,UAAzB,CACV,CAFD,CASAlC,CAAK,CAACuB,SAAN,CAAgBuE,QAAhB,CAA2B,UAAW,CAClC,GAAI,KAAKC,OAAL,EAAJ,CAAoB,CAChB,MACH,CAED,KAAKrD,QAAL,GAAgBiD,WAAhB,CAA4B,UAA5B,CACH,CAND,CAcA3F,CAAK,CAACuB,SAAN,CAAgBwE,OAAhB,CAA0B,UAAW,CACjC,MAAO,CAAC,KAAKrD,QAAL,GAAgBR,QAAhB,CAAyB,UAAzB,CACX,CAFD,CAUAlC,CAAK,CAACuB,SAAN,CAAgByE,aAAhB,CAAgC,SAAS7C,CAAT,CAAgB,CAC5C,GAAI,CAACA,CAAL,CAAY,CACR,KAAKT,QAAL,GAAgB,CAAhB,EAAmBuD,SAAnB,CAA6BC,MAA7B,CAAoC,yBAApC,EACA,MACH,CAED,KAAKxD,QAAL,GAAgB,CAAhB,EAAmBuD,SAAnB,CAA6BE,GAA7B,CAAiC,yBAAjC,CACH,CAPD,CAgBAnG,CAAK,CAACuB,SAAN,CAAgB6E,eAAhB,CAAkC,UAAW,IACrCC,CAAAA,CAAK,CAAGnI,CAAC,CAACY,CAAS,CAACQ,MAAV,CAAmB,IAAnB,CAA0BR,CAAS,CAACU,QAApC,CAA+C,IAA/C,CAAsDV,CAAS,CAACW,WAAjE,CAD4B,CAErC6G,CAAM,CAAGC,QAAQ,CAAC,KAAKtG,IAAL,CAAU+D,GAAV,CAAc,SAAd,CAAD,CAFoB,CAIzCqC,CAAK,CAACtE,IAAN,CAAW,SAASC,CAAT,CAAgBwE,CAAhB,CAAsB,CAC7BA,CAAI,CAAGtI,CAAC,CAACsI,CAAD,CAAR,CAGA,GAAIC,CAAAA,CAAU,CAAGD,CAAI,CAACxC,GAAL,CAAS,SAAT,EAAsBuC,QAAQ,CAACC,CAAI,CAACxC,GAAL,CAAS,SAAT,CAAD,CAA9B,CAAsD,CAAvE,CAEA,GAAIyC,CAAU,CAAGH,CAAjB,CAAyB,CACrBA,CAAM,CAAGG,CACZ,CACJ,CATD,EAWA,MAAOH,CAAAA,CACV,CAhBD,CAwBAtG,CAAK,CAACuB,SAAN,CAAgBsD,SAAhB,CAA4B,UAAW,CACnC,MAAO,MAAK5E,IAAL,CAAUiC,QAAV,CAAmB,MAAnB,CACV,CAFD,CAUAlC,CAAK,CAACuB,SAAN,CAAgBmF,QAAhB,CAA2B,UAAW,CAClC,GAAIC,CAAAA,CAAM,CAAGzI,CAAC,CAAC0I,QAAQ,CAACC,aAAV,CAAd,CACA,MAAO,MAAK5G,IAAL,CAAUiB,EAAV,CAAayF,CAAb,GAAwB,KAAK1G,IAAL,CAAU6G,GAAV,CAAcH,CAAd,EAAsBtF,MACxD,CAHD,CAWArB,CAAK,CAACuB,SAAN,CAAgBwF,cAAhB,CAAiC,UAAW,CACxC,MAAO,MAAKtE,OAAL,GAAeP,QAAf,CAAwB,MAAxB,CACV,CAFD,CASAlC,CAAK,CAACuB,SAAN,CAAgBE,kBAAhB,CAAqC,UAAW,CAC5C,MAAOvD,CAAAA,CAAC,CAACW,CAAU,CAACmI,UAAX,IAA2BJ,QAAQ,CAACnG,IAArC,CACX,CAFD,CAWAT,CAAK,CAACuB,SAAN,CAAgB0F,IAAhB,CAAuB,UAAW,CAC9B,GAAI,KAAKpC,SAAL,EAAJ,CAAsB,CAClB,MAAO3G,CAAAA,CAAC,CAACoC,QAAF,GAAa+C,OAAb,EACV,CAED,GAAI6D,CAAAA,CAAc,CAAG,GAAIvI,CAAAA,CAAJ,CAAY,iBAAZ,CAArB,CAEA,GAAI,KAAK4G,gBAAL,EAAJ,CAA6B,CACzB,KAAKD,UAAL,EACH,CAFD,IAEO,CACH,KAAKG,UAAL,EACH,CAED,KAAKjE,WAAL,GAEA,MAAO,MAAKY,WAAL,GACNE,IADM,CACD,SAAS6E,CAAT,CAAmB,IACjBC,CAAAA,CAAY,CAAG,KAAKhB,eAAL,EADE,CAEjBiB,CAAQ,CAAGD,CAAY,CAAG,CAFT,CAIrB,KAAKnH,IAAL,CAAU+D,GAAV,CAAc,SAAd,CAAyBqD,CAAzB,EACAF,CAAQ,CAACG,SAAT,CAFuBD,CAAQ,CAAG,CAElC,EACAF,CAAQ,CAACF,IAAT,GAEA,KAAKhH,IAAL,CAAU0F,WAAV,CAAsB,MAAtB,EAA8BD,QAA9B,CAAuC,MAAvC,EACA,KAAK6B,iBAAL,GACA,KAAK7E,QAAL,GAAgB8E,KAAhB,GACAtJ,CAAC,CAAC,MAAD,CAAD,CAAUwH,QAAV,CAAmB,YAAnB,EACA,KAAKzF,IAAL,CAAUwD,OAAV,CAAkBhF,CAAW,CAACgJ,KAA9B,CAAqC,IAArC,CAGH,CAfK,CAeJtF,IAfI,CAeC,IAfD,CADC,EAiBNG,IAjBM,CAiBD4E,CAAc,CAAC7D,OAjBd,CAkBV,CAjCD,CAwCArD,CAAK,CAACuB,SAAN,CAAgBmG,aAAhB,CAAgC,UAAW,CACvC,GAAIC,CAAAA,CAAW,CAAG,KAAKzH,KAAL,CAAWC,IAAX,CAAgBrB,CAAS,CAACS,IAA1B,CAAlB,CACA,GAA0B,CAAtB,EAAAoI,CAAW,CAACtG,MAAhB,CAA6B,CACzB,KAAKkD,IAAL,EACH,CACJ,CALD,CAYAvE,CAAK,CAACuB,SAAN,CAAgBgD,IAAhB,CAAuB,UAAW,CAC9B,KAAKnC,WAAL,GAAmBwF,IAAnB,CAAwB,SAAST,CAAT,CAAmB,CACvCzI,CAAS,CAACmJ,WAAV,GAEA,GAAI,CAAC,KAAKhG,uBAAL,EAAL,CAAqC,CAEjCsF,CAAQ,CAAC5C,IAAT,GACArG,CAAC,CAAC,MAAD,CAAD,CAAUyH,WAAV,CAAsB,YAAtB,CACH,CAED,GAAIyB,CAAAA,CAAY,CAAGb,QAAQ,CAAC,KAAKtG,IAAL,CAAU+D,GAAV,CAAc,SAAd,CAAD,CAA3B,CACA,KAAK/D,IAAL,CAAU+D,GAAV,CAAc,SAAd,CAAyB,EAAzB,EACAmD,CAAQ,CAACG,SAAT,CAAmBF,CAAY,CAAG,CAAlC,EAEA,KAAKU,iBAAL,GAEA,GAAI,KAAKf,cAAL,EAAJ,CAA2B,CAEvB,KAAKtE,OAAL,GAAesF,GAAf,CAAmB,kDAAnB,CAAuE,UAAW,CAC9E,KAAKtF,OAAL,GAAekD,WAAf,CAA2B,MAA3B,EAAmCD,QAAnC,CAA4C,MAA5C,CACH,CAFsE,CAErEvD,IAFqE,CAEhE,IAFgE,CAAvE,CAGH,CALD,IAKO,CACH,KAAKM,OAAL,GAAekD,WAAf,CAA2B,MAA3B,EAAmCD,QAAnC,CAA4C,MAA5C,CACH,CAGDxH,CAAC,CAAC0I,QAAQ,CAACnG,IAAV,CAAD,CAAiBiB,MAAjB,CAAwB,KAAKe,OAAL,EAAxB,EAEA,KAAKxC,IAAL,CAAUwD,OAAV,CAAkBhF,CAAW,CAACuJ,MAA9B,CAAsC,IAAtC,CACH,CA5BuB,CA4BtB7F,IA5BsB,CA4BjB,IA5BiB,CAAxB,CA6BH,CA9BD,CAqCAnC,CAAK,CAACuB,SAAN,CAAgB0G,OAAhB,CAA0B,UAAW,CACjC,KAAK1D,IAAL,GACA,KAAKtE,IAAL,CAAUiG,MAAV,GACA,KAAKjG,IAAL,CAAUwD,OAAV,CAAkBhF,CAAW,CAACyJ,SAA9B,CAAyC,IAAzC,CACH,CAJD,CAaAlI,CAAK,CAACuB,SAAN,CAAgBgG,iBAAhB,CAAoC,UAAW,CAE3C3I,CAAI,CAACuJ,MAAL,CAAY,KAAKlI,IAAL,CAAUmI,GAAV,EAAZ,EAGAxJ,CAAI,CAACyJ,YAAL,CAAkB,KAAKpI,IAAL,CAAUmI,GAAV,GAAgB,CAAhB,CAAlB,CACH,CAND,CAeApI,CAAK,CAACuB,SAAN,CAAgBuG,iBAAhB,CAAoC,UAAW,CAE3ClJ,CAAI,CAAC0J,cAAL,CAAoB,KAAKrI,IAAL,CAAUmI,GAAV,GAAgB,CAAhB,CAApB,EAGAxJ,CAAI,CAAC2F,IAAL,CAAU,KAAKtE,IAAL,CAAUmI,GAAV,EAAV,CACH,CAND,CAaApI,CAAK,CAACuB,SAAN,CAAgBD,sBAAhB,CAAyC,UAAW,CAChD,KAAKmB,OAAL,GAAe8F,EAAf,CAAkB,SAAlB,CAA6B,SAASC,CAAT,CAAY,CACrC,GAAI,CAAC,KAAK3D,SAAL,EAAL,CAAuB,CACnB,MACH,CAED,GAAI2D,CAAC,CAACC,OAAF,EAAapK,CAAQ,CAACqK,MAA1B,CAAkC,CAC9B,KAAKnE,IAAL,EACH,CACJ,CAR4B,CAQ3BpC,IAR2B,CAQtB,IARsB,CAA7B,EAWA,KAAKM,OAAL,GAAekG,KAAf,CAAqB,SAASH,CAAT,CAAY,CAG7B,GAAI,CAACtK,CAAC,CAACsK,CAAC,CAAC7B,MAAH,CAAD,CAAYiC,OAAZ,CAAoB9J,CAAS,CAACE,KAA9B,EAAqCqC,MAA1C,CAAkD,CAI9C,GAAInD,CAAC,CAACsK,CAAC,CAAC7B,MAAH,CAAD,CAAYiC,OAAZ,CAAoB9J,CAAS,CAACC,SAA9B,EAAyCsC,MAA7C,CAAqD,CACjD,GAAIwH,CAAAA,CAAiB,CAAG3K,CAAC,CAACM,KAAF,CAAQC,CAAW,CAACqK,YAApB,CAAxB,CACA,KAAKrG,OAAL,GAAegB,OAAf,CAAuBoF,CAAvB,CAA0C,IAA1C,EAEA,GAAI,CAACA,CAAiB,CAACE,kBAAlB,EAAL,CAA6C,CACzC,KAAKrB,aAAL,EACH,CACJ,CACJ,CACJ,CAhBoB,CAgBnBvF,IAhBmB,CAgBd,IAhBc,CAArB,EAkBA7D,CAAY,CAACL,MAAb,CAAoB,KAAKyE,QAAL,EAApB,CAAqC,CAACpE,CAAY,CAAC0K,MAAb,CAAoBC,QAArB,CAArC,EACA,KAAKvG,QAAL,GAAgB6F,EAAhB,CAAmBjK,CAAY,CAAC0K,MAAb,CAAoBC,QAAvC,CAAiDnK,CAAS,CAACO,IAA3D,CAAiE,SAASmJ,CAAT,CAAYU,CAAZ,CAAkB,CAC/E,KAAK3E,IAAL,GACA2E,CAAI,CAACC,aAAL,CAAmBC,cAAnB,EACH,CAHgE,CAG/DjH,IAH+D,CAG1D,IAH0D,CAAjE,CAIH,CAnCD,CA0CAnC,CAAK,CAACuB,SAAN,CAAgB8H,qBAAhB,CAAwC,UAAW,CAE/C,KAAK3G,QAAL,GAAgB6F,EAAhB,CAAmBjK,CAAY,CAAC0K,MAAb,CAAoBC,QAAvC,CAAiD,KAAKK,iBAAL,CAAuB,QAAvB,CAAjD,CAAmF,SAASd,CAAT,CAAYU,CAAZ,CAAkB,CACjG,GAAIK,CAAAA,CAAW,CAAGrL,CAAC,CAACM,KAAF,CAAQC,CAAW,CAAC+K,MAApB,CAAlB,CACA,KAAK/G,OAAL,GAAegB,OAAf,CAAuB8F,CAAvB,CAAoC,IAApC,EAEA,GAAI,CAACA,CAAW,CAACR,kBAAZ,EAAL,CAAuC,CACnCG,CAAI,CAACC,aAAL,CAAmBC,cAAnB,GAEA,GAAI,KAAKK,aAAT,CAAwB,CACpB,KAAKxB,OAAL,EACH,CAFD,IAEO,CACH,KAAK1D,IAAL,EACH,CACJ,CACJ,CAbkF,CAajFpC,IAbiF,CAa5E,IAb4E,CAAnF,CAcH,CAhBD,CAuBAnC,CAAK,CAACuB,SAAN,CAAgBmI,mBAAhB,CAAsC,UAAW,CAE7C,KAAKhH,QAAL,GAAgB6F,EAAhB,CAAmBjK,CAAY,CAAC0K,MAAb,CAAoBC,QAAvC,CAAiD,KAAKK,iBAAL,CAAuB,MAAvB,CAAjD,CAAiF,SAASd,CAAT,CAAYU,CAAZ,CAAkB,CAC/F,GAAIS,CAAAA,CAAS,CAAGzL,CAAC,CAACM,KAAF,CAAQC,CAAW,CAACmL,IAApB,CAAhB,CACA,KAAKnH,OAAL,GAAegB,OAAf,CAAuBkG,CAAvB,CAAkC,IAAlC,EAEA,GAAI,CAACA,CAAS,CAACZ,kBAAV,EAAL,CAAqC,CACjCG,CAAI,CAACC,aAAL,CAAmBC,cAAnB,GAEA,GAAI,KAAKK,aAAT,CAAwB,CACpB,KAAKxB,OAAL,EACH,CAFD,IAEO,CACH,KAAK1D,IAAL,EACH,CACJ,CACJ,CAbgF,CAa/EpC,IAb+E,CAa1E,IAb0E,CAAjF,CAcH,CAhBD,CA0BAnC,CAAK,CAACuB,SAAN,CAAgB6B,QAAhB,CAA2B,SAASD,CAAT,CAAgB0G,CAAhB,CAA6B,CACpD,GAAIC,CAAAA,CAAC,CAAG3G,CAAR,CACA,GAAqB,QAAjB,WAAOA,CAAP,GAA6B,CAACA,CAAK,CAAC4G,cAAN,CAAqB,MAArB,CAAlC,CAAgE,CAC5DD,CAAC,CAAG5L,CAAC,CAACoC,QAAF,EAAJ,CACAwJ,CAAC,CAACzG,OAAF,CAAUF,CAAV,CACH,CAED2G,CAAC,CAACxH,IAAF,CAAO,SAAS0H,CAAT,CAAkB,CACrBH,CAAW,CAACG,CAAD,CAGd,CAJD,EAKCxH,IALD,CAKMpE,CAAY,CAAC+C,SALnB,EAOA,MAAO2I,CAAAA,CACV,CAfD,CA2BA9J,CAAK,CAACuB,SAAN,CAAgB0I,aAAhB,CAAgC,SAASC,CAAT,CAAiB/G,CAAjB,CAAwB,CACpD,GAAMgH,CAAAA,CAAM,CAAG,KAAKtH,SAAL,GAAiB1C,IAAjB,CAAsB,KAAKmJ,iBAAL,CAAuBY,CAAvB,CAAtB,CAAf,CAEA,GAAI,CAACC,CAAL,CAAa,CACT,KAAM,IAAIC,CAAAA,KAAJ,CAAU,uBAAyBF,CAAzB,CAAkC,UAA5C,CACT,CAED,MAAO,MAAK9G,QAAL,CAAcD,CAAd,CAAqBgH,CAAM,CAACE,IAAP,CAAYlI,IAAZ,CAAiBgI,CAAjB,CAArB,CACV,CARD,CAgBAnK,CAAK,CAACuB,SAAN,CAAgB+H,iBAAhB,CAAoC,SAASY,CAAT,CAAiB,CACjD,MAAO,iBAAmBA,CAAnB,CAA4B,IACtC,CAFD,CASAlK,CAAK,CAACuB,SAAN,CAAgB+I,gBAAhB,CAAmC,SAASpE,CAAT,CAAiB,CAChD,KAAKuD,aAAL,CAAqBvD,CACxB,CAFD,CAIA,MAAOlG,CAAAA,CACV,CAl5BK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Contain the logic for modals.\n *\n * @module core/modal\n * @class modal\n * @package core\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core/key_codes',\n 'core/custom_interaction_events',\n 'core/modal_backdrop',\n 'core/event',\n 'core/modal_events',\n 'core/local/aria/focuslock',\n 'core/pending',\n 'core/aria',\n 'core/fullscreen'\n], function(\n $,\n Templates,\n Notification,\n KeyCodes,\n CustomEvents,\n ModalBackdrop,\n Event,\n ModalEvents,\n FocusLock,\n Pending,\n Aria,\n Fullscreen\n) {\n\n var 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\n var TEMPLATES = {\n LOADING: 'core/loading',\n BACKDROP: 'core/modal_backdrop',\n };\n\n /**\n * Module singleton for the backdrop to be reused by all Modal instances.\n */\n var backdropPromise;\n\n /**\n * A counter that gets incremented for each modal created. This can be\n * used to generate unique values for the modals.\n */\n var modalCounter = 0;\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var Modal = function(root) {\n this.root = $(root);\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 = modalCounter++;\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 * 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 Modal.prototype.attachToDOM = function() {\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 Modal.prototype.countOtherVisibleModals = function() {\n var count = 0;\n $('body').find(SELECTORS.CONTAINER).each(function(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 }.bind(this));\n\n return count;\n };\n\n /**\n * Get the modal backdrop.\n *\n * @method getBackdrop\n * @return {object} jQuery promise\n */\n Modal.prototype.getBackdrop = function() {\n if (!backdropPromise) {\n backdropPromise = Templates.render(TEMPLATES.BACKDROP, {})\n .then(function(html) {\n var element = $(html);\n\n return new ModalBackdrop(element);\n })\n .fail(Notification.exception);\n }\n\n return backdropPromise;\n };\n\n /**\n * Get the root element of this modal.\n *\n * @method getRoot\n * @return {object} jQuery object\n */\n Modal.prototype.getRoot = function() {\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 Modal.prototype.getModal = function() {\n return this.modal;\n };\n\n /**\n * Get the modal title element.\n *\n * @method getTitle\n * @return {object} jQuery object\n */\n Modal.prototype.getTitle = function() {\n return this.title;\n };\n\n /**\n * Get the modal body element.\n *\n * @method getBody\n * @return {object} jQuery object\n */\n Modal.prototype.getBody = function() {\n return this.body;\n };\n\n /**\n * Get the modal footer element.\n *\n * @method getFooter\n * @return {object} jQuery object\n */\n Modal.prototype.getFooter = function() {\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 Modal.prototype.getTitlePromise = function() {\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 Modal.prototype.getBodyPromise = function() {\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 Modal.prototype.getFooterPromise = function() {\n return this.footerPromise;\n };\n\n /**\n * Get the unique modal count.\n *\n * @method getModalCount\n * @return {int}\n */\n Modal.prototype.getModalCount = function() {\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 Modal.prototype.setTitle = function(value) {\n var title = this.getTitle();\n this.titlePromise = $.Deferred();\n\n this.asyncSet(value, title.html.bind(title))\n .then(function() {\n this.titlePromise.resolve(title);\n }.bind(this))\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 */\n Modal.prototype.setBody = function(value) {\n this.bodyPromise = $.Deferred();\n\n var body = this.getBody();\n\n if (typeof value === 'string') {\n // Just set the value if it's a string.\n body.html(value);\n Event.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n this.bodyPromise.resolve(body);\n } else {\n var jsPendingId = 'amd-modal-js-pending-id-' + this.getModalCount();\n M.util.js_pending(jsPendingId);\n // Otherwise we assume it's a promise to be resolved with\n // html and javascript.\n var 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 var 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(function(html) {\n var 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(function(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(function() {\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(function(html, js) {\n var 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 var 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 var 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 }.bind(this))\n .then(function(result) {\n Event.notifyFilterContentUpdated(body);\n this.getRoot().trigger(ModalEvents.bodyRendered, this);\n return result;\n }.bind(this))\n .then(function() {\n this.bodyPromise.resolve(body);\n return;\n }.bind(this))\n .fail(Notification.exception)\n .always(function() {\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 M.util.js_complete(jsPendingId);\n\n return;\n })\n .fail(Notification.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 Modal.prototype.setFooter = function(value) {\n // Make sure the footer is visible.\n this.showFooter();\n this.footerPromise = $.Deferred();\n\n var 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(function(html) {\n footer.html(html);\n\n return value;\n })\n .then(function(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 }.bind(this))\n .then(function(footer) {\n this.footerPromise.resolve(footer);\n return;\n }.bind(this))\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 Modal.prototype.hasFooterContent = function() {\n return this.getFooter().children().length ? true : false;\n };\n\n /**\n * Hide the footer element.\n *\n * @method hideFooter\n */\n Modal.prototype.hideFooter = function() {\n this.getFooter().addClass('hidden');\n };\n\n /**\n * Show the footer element.\n *\n * @method showFooter\n */\n Modal.prototype.showFooter = function() {\n this.getFooter().removeClass('hidden');\n };\n\n /**\n * Mark the modal as a large modal.\n *\n * @method setLarge\n */\n Modal.prototype.setLarge = function() {\n if (this.isLarge()) {\n return;\n }\n\n this.getModal().addClass('modal-lg');\n };\n\n /**\n * Check if the modal is a large modal.\n *\n * @method isLarge\n * @return {bool}\n */\n Modal.prototype.isLarge = function() {\n return this.getModal().hasClass('modal-lg');\n };\n\n /**\n * Mark the modal as a small modal.\n *\n * @method setSmall\n */\n Modal.prototype.setSmall = function() {\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 Modal.prototype.isSmall = function() {\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 Modal.prototype.setScrollable = function(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 Modal.prototype.calculateZIndex = function() {\n var items = $(SELECTORS.DIALOG + ', ' + SELECTORS.MENU_BAR + ', ' + SELECTORS.HAS_Z_INDEX);\n var zIndex = parseInt(this.root.css('z-index'));\n\n items.each(function(index, item) {\n item = $(item);\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 var 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 Modal.prototype.isVisible = function() {\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 Modal.prototype.hasFocus = function() {\n var 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 Modal.prototype.hasTransitions = function() {\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 Modal.prototype.getAttachmentPoint = function() {\n return $(Fullscreen.getElement() || document.body);\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 Modal.prototype.show = function() {\n if (this.isVisible()) {\n return $.Deferred().resolve();\n }\n\n var 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 return this.getBackdrop()\n .then(function(backdrop) {\n var currentIndex = this.calculateZIndex();\n var newIndex = currentIndex + 2;\n var 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 }.bind(this))\n .then(pendingPromise.resolve);\n };\n\n /**\n * Hide this modal if it does not contain a form.\n *\n * @method hideIfNotForm\n */\n Modal.prototype.hideIfNotForm = function() {\n var 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 Modal.prototype.hide = function() {\n this.getBackdrop().done(function(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 var 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', function() {\n this.getRoot().removeClass('show').addClass('hide');\n }.bind(this));\n } else {\n this.getRoot().removeClass('show').addClass('hide');\n }\n\n // Ensure the modal is moved onto the body node.\n $(document.body).append(this.getRoot());\n\n this.root.trigger(ModalEvents.hidden, this);\n }.bind(this));\n };\n\n /**\n * Remove this modal from the DOM.\n *\n * @method destroy\n */\n Modal.prototype.destroy = function() {\n this.hide();\n this.root.remove();\n this.root.trigger(ModalEvents.destroyed, this);\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 Modal.prototype.accessibilityShow = function() {\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 Modal.prototype.accessibilityHide = function() {\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 Modal.prototype.registerEventListeners = function() {\n this.getRoot().on('keydown', function(e) {\n if (!this.isVisible()) {\n return;\n }\n\n if (e.keyCode == KeyCodes.escape) {\n this.hide();\n }\n }.bind(this));\n\n // Listen for clicks on the modal container.\n this.getRoot().click(function(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 var outsideClickEvent = $.Event(ModalEvents.outsideClick);\n this.getRoot().trigger(outsideClickEvent, this);\n\n if (!outsideClickEvent.isDefaultPrevented()) {\n this.hideIfNotForm();\n }\n }\n }\n }.bind(this));\n\n CustomEvents.define(this.getModal(), [CustomEvents.events.activate]);\n this.getModal().on(CustomEvents.events.activate, SELECTORS.HIDE, function(e, data) {\n this.hide();\n data.originalEvent.preventDefault();\n }.bind(this));\n };\n\n /**\n * Register a listener to close the dialogue when the cancel button is pressed.\n *\n * @method registerCloseOnCancel\n */\n Modal.prototype.registerCloseOnCancel = function() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('cancel'), function(e, data) {\n var 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 }.bind(this));\n };\n\n /**\n * Register a listener to close the dialogue when the save button is pressed.\n *\n * @method registerCloseOnSave\n */\n Modal.prototype.registerCloseOnSave = function() {\n // Handle the clicking of the Cancel button.\n this.getModal().on(CustomEvents.events.activate, this.getActionSelector('save'), function(e, data) {\n var 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 }.bind(this));\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 Modal.prototype.asyncSet = function(value, setFunction) {\n var p = value;\n if (typeof value !== 'object' || !value.hasOwnProperty('then')) {\n p = $.Deferred();\n p.resolve(value);\n }\n\n p.then(function(content) {\n setFunction(content);\n\n return;\n })\n .fail(Notification.exception);\n\n return p;\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 Modal.prototype.setButtonText = function(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 Modal.prototype.getActionSelector = function(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 Modal.prototype.setRemoveOnClose = function(remove) {\n this.removeOnClose = remove;\n };\n\n return Modal;\n});\n"],"file":"modal.min.js"} \ No newline at end of file diff --git a/lib/amd/build/modal_backdrop.min.js b/lib/amd/build/modal_backdrop.min.js index dfedcaef845..ec09403c485 100644 --- a/lib/amd/build/modal_backdrop.min.js +++ b/lib/amd/build/modal_backdrop.min.js @@ -1,2 +1,2 @@ -define ("core/modal_backdrop",["jquery","core/templates","core/notification"],function(a,b,c){var d={ROOT:"[data-region=\"modal-backdrop\"]"},e=function(b){this.root=a(b);this.isAttached=!1;if(!this.root.is(d.ROOT)){c.exception({message:"Element is not a modal backdrop"})}};e.prototype.getRoot=function(){return this.root};e.prototype.attachToDOM=function(){if(this.isAttached){return}a("body").append(this.root);this.isAttached=!0};e.prototype.setZIndex=function(a){this.root.css("z-index",a)};e.prototype.isVisible=function(){return this.root.hasClass("show")};e.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")};e.prototype.show=function(){if(this.isVisible()){return}if(!this.isAttached){this.attachToDOM()}this.root.removeClass("hide").addClass("show")};e.prototype.hide=function(){if(!this.isVisible()){return}if(this.hasTransitions()){this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",function(){this.getRoot().removeClass("show").addClass("hide")}.bind(this))}else{this.getRoot().removeClass("show").addClass("hide")}};e.prototype.destroy=function(){this.root.remove()};return e}); +define ("core/modal_backdrop",["jquery","core/templates","core/notification","core/fullscreen"],function(a,b,c,d){var e={ROOT:"[data-region=\"modal-backdrop\"]"},f=function(b){this.root=a(b);this.isAttached=!1;if(!this.root.is(e.ROOT)){c.exception({message:"Element is not a modal backdrop"})}};f.prototype.getRoot=function(){return this.root};f.prototype.getAttachmentPoint=function(){return a(d.getElement()||document.body)};f.prototype.attachToDOM=function(){this.getAttachmentPoint().append(this.root);if(this.isAttached){return}this.isAttached=!0};f.prototype.setZIndex=function(a){this.root.css("z-index",a)};f.prototype.isVisible=function(){return this.root.hasClass("show")};f.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")};f.prototype.show=function(){if(this.isVisible()){return}this.attachToDOM();this.root.removeClass("hide").addClass("show")};f.prototype.hide=function(){if(!this.isVisible()){return}if(this.hasTransitions()){this.getRoot().one("transitionend webkitTransitionEnd oTransitionEnd",function(){this.getRoot().removeClass("show").addClass("hide")}.bind(this))}else{this.getRoot().removeClass("show").addClass("hide")}a(document.body).append(this.getRoot())};f.prototype.destroy=function(){this.root.remove()};return f}); //# sourceMappingURL=modal_backdrop.min.js.map diff --git a/lib/amd/build/modal_backdrop.min.js.map b/lib/amd/build/modal_backdrop.min.js.map index 9b2bf43436f..27718d9fd6d 100644 --- a/lib/amd/build/modal_backdrop.min.js.map +++ b/lib/amd/build/modal_backdrop.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/modal_backdrop.js"],"names":["define","$","Templates","Notification","SELECTORS","ROOT","ModalBackdrop","root","isAttached","is","exception","message","prototype","getRoot","attachToDOM","append","setZIndex","value","css","isVisible","hasClass","hasTransitions","show","removeClass","addClass","hide","one","bind","destroy","remove"],"mappings":"AAwBAA,OAAM,uBAAC,CAAC,QAAD,CAAW,gBAAX,CAA6B,mBAA7B,CAAD,CACD,SAASC,CAAT,CAAYC,CAAZ,CAAuBC,CAAvB,CAAqC,IAElCC,CAAAA,CAAS,CAAG,CACZC,IAAI,CAAE,kCADM,CAFsB,CAWlCC,CAAa,CAAG,SAASC,CAAT,CAAe,CAC/B,KAAKA,IAAL,CAAYN,CAAC,CAACM,CAAD,CAAb,CACA,KAAKC,UAAL,IAEA,GAAI,CAAC,KAAKD,IAAL,CAAUE,EAAV,CAAaL,CAAS,CAACC,IAAvB,CAAL,CAAmC,CAC/BF,CAAY,CAACO,SAAb,CAAuB,CAACC,OAAO,CAAE,iCAAV,CAAvB,CACH,CACJ,CAlBqC,CA0BtCL,CAAa,CAACM,SAAd,CAAwBC,OAAxB,CAAkC,UAAW,CACzC,MAAO,MAAKN,IACf,CAFD,CASAD,CAAa,CAACM,SAAd,CAAwBE,WAAxB,CAAsC,UAAW,CAC7C,GAAI,KAAKN,UAAT,CAAqB,CACjB,MACH,CAEDP,CAAC,CAAC,MAAD,CAAD,CAAUc,MAAV,CAAiB,KAAKR,IAAtB,EACA,KAAKC,UAAL,GACH,CAPD,CAeAF,CAAa,CAACM,SAAd,CAAwBI,SAAxB,CAAoC,SAASC,CAAT,CAAgB,CAChD,KAAKV,IAAL,CAAUW,GAAV,CAAc,SAAd,CAAyBD,CAAzB,CACH,CAFD,CAUAX,CAAa,CAACM,SAAd,CAAwBO,SAAxB,CAAoC,UAAW,CAC3C,MAAO,MAAKZ,IAAL,CAAUa,QAAV,CAAmB,MAAnB,CACV,CAFD,CAUAd,CAAa,CAACM,SAAd,CAAwBS,cAAxB,CAAyC,UAAW,CAChD,MAAO,MAAKR,OAAL,GAAeO,QAAf,CAAwB,MAAxB,CACV,CAFD,CAUAd,CAAa,CAACM,SAAd,CAAwBU,IAAxB,CAA+B,UAAW,CACtC,GAAI,KAAKH,SAAL,EAAJ,CAAsB,CAClB,MACH,CAED,GAAI,CAAC,KAAKX,UAAV,CAAsB,CAClB,KAAKM,WAAL,EACH,CAED,KAAKP,IAAL,CAAUgB,WAAV,CAAsB,MAAtB,EAA8BC,QAA9B,CAAuC,MAAvC,CACH,CAVD,CAiBAlB,CAAa,CAACM,SAAd,CAAwBa,IAAxB,CAA+B,UAAW,CACtC,GAAI,CAAC,KAAKN,SAAL,EAAL,CAAuB,CACnB,MACH,CAED,GAAI,KAAKE,cAAL,EAAJ,CAA2B,CAEvB,KAAKR,OAAL,GAAea,GAAf,CAAmB,kDAAnB,CAAuE,UAAW,CAC9E,KAAKb,OAAL,GAAeU,WAAf,CAA2B,MAA3B,EAAmCC,QAAnC,CAA4C,MAA5C,CACH,CAFsE,CAErEG,IAFqE,CAEhE,IAFgE,CAAvE,CAGH,CALD,IAKO,CACH,KAAKd,OAAL,GAAeU,WAAf,CAA2B,MAA3B,EAAmCC,QAAnC,CAA4C,MAA5C,CACH,CACJ,CAbD,CAoBAlB,CAAa,CAACM,SAAd,CAAwBgB,OAAxB,CAAkC,UAAW,CACzC,KAAKrB,IAAL,CAAUsB,MAAV,EACH,CAFD,CAIA,MAAOvB,CAAAA,CACV,CA3HK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Contain the logic for modal backdrops.\n *\n * @module core/modal_backdrop\n * @class modal_backdrop\n * @package core\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates', 'core/notification'],\n function($, Templates, Notification) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"modal-backdrop\"]',\n };\n\n /**\n * Constructor for ModalBackdrop.\n *\n * @param {object} root The root element for the modal backdrop\n */\n var ModalBackdrop = function(root) {\n this.root = $(root);\n this.isAttached = false;\n\n if (!this.root.is(SELECTORS.ROOT)) {\n Notification.exception({message: 'Element is not a modal backdrop'});\n }\n };\n\n /**\n * Get the root element of this modal backdrop.\n *\n * @method getRoot\n * @return {object} jQuery object\n */\n ModalBackdrop.prototype.getRoot = function() {\n return this.root;\n };\n\n /**\n * Add the modal backdrop to the page, if it hasn't already been added.\n *\n * @method attachToDOM\n */\n ModalBackdrop.prototype.attachToDOM = function() {\n if (this.isAttached) {\n return;\n }\n\n $('body').append(this.root);\n this.isAttached = true;\n };\n\n /**\n * Set the z-index value for this backdrop.\n *\n * @method setZIndex\n * @param {int} value The z-index value\n */\n ModalBackdrop.prototype.setZIndex = function(value) {\n this.root.css('z-index', value);\n };\n\n /**\n * Check if this backdrop is visible.\n *\n * @method isVisible\n * @return {bool}\n */\n ModalBackdrop.prototype.isVisible = function() {\n return this.root.hasClass('show');\n };\n\n /**\n * Check if this backdrop has CSS transitions applied.\n *\n * @method hasTransitions\n * @return {bool}\n */\n ModalBackdrop.prototype.hasTransitions = function() {\n return this.getRoot().hasClass('fade');\n };\n\n /**\n * Display this backdrop. The backdrop will be attached to the DOM if it hasn't\n * already been.\n *\n * @method show\n */\n ModalBackdrop.prototype.show = function() {\n if (this.isVisible()) {\n return;\n }\n\n if (!this.isAttached) {\n this.attachToDOM();\n }\n\n this.root.removeClass('hide').addClass('show');\n };\n\n /**\n * Hide this backdrop.\n *\n * @method hide\n */\n ModalBackdrop.prototype.hide = function() {\n if (!this.isVisible()) {\n return;\n }\n\n if (this.hasTransitions()) {\n // Wait for CSS transitions to complete before hiding the element.\n this.getRoot().one('transitionend webkitTransitionEnd oTransitionEnd', function() {\n this.getRoot().removeClass('show').addClass('hide');\n }.bind(this));\n } else {\n this.getRoot().removeClass('show').addClass('hide');\n }\n };\n\n /**\n * Remove this backdrop from the DOM.\n *\n * @method destroy\n */\n ModalBackdrop.prototype.destroy = function() {\n this.root.remove();\n };\n\n return ModalBackdrop;\n});\n"],"file":"modal_backdrop.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/modal_backdrop.js"],"names":["define","$","Templates","Notification","Fullscreen","SELECTORS","ROOT","ModalBackdrop","root","isAttached","is","exception","message","prototype","getRoot","getAttachmentPoint","getElement","document","body","attachToDOM","append","setZIndex","value","css","isVisible","hasClass","hasTransitions","show","removeClass","addClass","hide","one","bind","destroy","remove"],"mappings":"AAwBAA,OAAM,uBAAC,CAAC,QAAD,CAAW,gBAAX,CAA6B,mBAA7B,CAAkD,iBAAlD,CAAD,CACD,SAASC,CAAT,CAAYC,CAAZ,CAAuBC,CAAvB,CAAqCC,CAArC,CAAiD,IAE9CC,CAAAA,CAAS,CAAG,CACZC,IAAI,CAAE,kCADM,CAFkC,CAW9CC,CAAa,CAAG,SAASC,CAAT,CAAe,CAC/B,KAAKA,IAAL,CAAYP,CAAC,CAACO,CAAD,CAAb,CACA,KAAKC,UAAL,IAEA,GAAI,CAAC,KAAKD,IAAL,CAAUE,EAAV,CAAaL,CAAS,CAACC,IAAvB,CAAL,CAAmC,CAC/BH,CAAY,CAACQ,SAAb,CAAuB,CAACC,OAAO,CAAE,iCAAV,CAAvB,CACH,CACJ,CAlBiD,CA0BlDL,CAAa,CAACM,SAAd,CAAwBC,OAAxB,CAAkC,UAAW,CACzC,MAAO,MAAKN,IACf,CAFD,CASCD,CAAa,CAACM,SAAd,CAAwBE,kBAAxB,CAA6C,UAAW,CACpD,MAAOd,CAAAA,CAAC,CAACG,CAAU,CAACY,UAAX,IAA2BC,QAAQ,CAACC,IAArC,CACX,CAFD,CASDX,CAAa,CAACM,SAAd,CAAwBM,WAAxB,CAAsC,UAAW,CAC7C,KAAKJ,kBAAL,GAA0BK,MAA1B,CAAiC,KAAKZ,IAAtC,EAEA,GAAI,KAAKC,UAAT,CAAqB,CACjB,MACH,CAED,KAAKA,UAAL,GACH,CARD,CAgBAF,CAAa,CAACM,SAAd,CAAwBQ,SAAxB,CAAoC,SAASC,CAAT,CAAgB,CAChD,KAAKd,IAAL,CAAUe,GAAV,CAAc,SAAd,CAAyBD,CAAzB,CACH,CAFD,CAUAf,CAAa,CAACM,SAAd,CAAwBW,SAAxB,CAAoC,UAAW,CAC3C,MAAO,MAAKhB,IAAL,CAAUiB,QAAV,CAAmB,MAAnB,CACV,CAFD,CAUAlB,CAAa,CAACM,SAAd,CAAwBa,cAAxB,CAAyC,UAAW,CAChD,MAAO,MAAKZ,OAAL,GAAeW,QAAf,CAAwB,MAAxB,CACV,CAFD,CAUAlB,CAAa,CAACM,SAAd,CAAwBc,IAAxB,CAA+B,UAAW,CACtC,GAAI,KAAKH,SAAL,EAAJ,CAAsB,CAClB,MACH,CAED,KAAKL,WAAL,GAEA,KAAKX,IAAL,CAAUoB,WAAV,CAAsB,MAAtB,EAA8BC,QAA9B,CAAuC,MAAvC,CACH,CARD,CAeAtB,CAAa,CAACM,SAAd,CAAwBiB,IAAxB,CAA+B,UAAW,CACtC,GAAI,CAAC,KAAKN,SAAL,EAAL,CAAuB,CACnB,MACH,CAED,GAAI,KAAKE,cAAL,EAAJ,CAA2B,CAEvB,KAAKZ,OAAL,GAAeiB,GAAf,CAAmB,kDAAnB,CAAuE,UAAW,CAC9E,KAAKjB,OAAL,GAAec,WAAf,CAA2B,MAA3B,EAAmCC,QAAnC,CAA4C,MAA5C,CACH,CAFsE,CAErEG,IAFqE,CAEhE,IAFgE,CAAvE,CAGH,CALD,IAKO,CACH,KAAKlB,OAAL,GAAec,WAAf,CAA2B,MAA3B,EAAmCC,QAAnC,CAA4C,MAA5C,CACH,CAGD5B,CAAC,CAACgB,QAAQ,CAACC,IAAV,CAAD,CAAiBE,MAAjB,CAAwB,KAAKN,OAAL,EAAxB,CACH,CAhBD,CAuBAP,CAAa,CAACM,SAAd,CAAwBoB,OAAxB,CAAkC,UAAW,CACzC,KAAKzB,IAAL,CAAU0B,MAAV,EACH,CAFD,CAIA,MAAO3B,CAAAA,CACV,CAtIK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Contain the logic for modal backdrops.\n *\n * @module core/modal_backdrop\n * @class modal_backdrop\n * @package core\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates', 'core/notification', 'core/fullscreen'],\n function($, Templates, Notification, Fullscreen) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"modal-backdrop\"]',\n };\n\n /**\n * Constructor for ModalBackdrop.\n *\n * @param {object} root The root element for the modal backdrop\n */\n var ModalBackdrop = function(root) {\n this.root = $(root);\n this.isAttached = false;\n\n if (!this.root.is(SELECTORS.ROOT)) {\n Notification.exception({message: 'Element is not a modal backdrop'});\n }\n };\n\n /**\n * Get the root element of this modal backdrop.\n *\n * @method getRoot\n * @return {object} jQuery object\n */\n ModalBackdrop.prototype.getRoot = function() {\n return this.root;\n };\n\n /**\n * Gets the jQuery wrapped node that the Modal should be attached to.\n *\n * @returns {jQuery}\n */\n ModalBackdrop.prototype.getAttachmentPoint = function() {\n return $(Fullscreen.getElement() || document.body);\n };\n\n /**\n * Add the modal backdrop to the page, if it hasn't already been added.\n *\n * @method attachToDOM\n */\n ModalBackdrop.prototype.attachToDOM = function() {\n this.getAttachmentPoint().append(this.root);\n\n if (this.isAttached) {\n return;\n }\n\n this.isAttached = true;\n };\n\n /**\n * Set the z-index value for this backdrop.\n *\n * @method setZIndex\n * @param {int} value The z-index value\n */\n ModalBackdrop.prototype.setZIndex = function(value) {\n this.root.css('z-index', value);\n };\n\n /**\n * Check if this backdrop is visible.\n *\n * @method isVisible\n * @return {bool}\n */\n ModalBackdrop.prototype.isVisible = function() {\n return this.root.hasClass('show');\n };\n\n /**\n * Check if this backdrop has CSS transitions applied.\n *\n * @method hasTransitions\n * @return {bool}\n */\n ModalBackdrop.prototype.hasTransitions = function() {\n return this.getRoot().hasClass('fade');\n };\n\n /**\n * Display this backdrop. The backdrop will be attached to the DOM if it hasn't\n * already been.\n *\n * @method show\n */\n ModalBackdrop.prototype.show = function() {\n if (this.isVisible()) {\n return;\n }\n\n this.attachToDOM();\n\n this.root.removeClass('hide').addClass('show');\n };\n\n /**\n * Hide this backdrop.\n *\n * @method hide\n */\n ModalBackdrop.prototype.hide = function() {\n if (!this.isVisible()) {\n return;\n }\n\n if (this.hasTransitions()) {\n // Wait for CSS transitions to complete before hiding the element.\n this.getRoot().one('transitionend webkitTransitionEnd oTransitionEnd', function() {\n this.getRoot().removeClass('show').addClass('hide');\n }.bind(this));\n } else {\n this.getRoot().removeClass('show').addClass('hide');\n }\n\n // Ensure the modal is moved back onto the body node.\n $(document.body).append(this.getRoot());\n };\n\n /**\n * Remove this backdrop from the DOM.\n *\n * @method destroy\n */\n ModalBackdrop.prototype.destroy = function() {\n this.root.remove();\n };\n\n return ModalBackdrop;\n});\n"],"file":"modal_backdrop.min.js"} \ No newline at end of file diff --git a/lib/amd/src/fullscreen.js b/lib/amd/src/fullscreen.js new file mode 100644 index 00000000000..4ac2acc5afe --- /dev/null +++ b/lib/amd/src/fullscreen.js @@ -0,0 +1,48 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Detects if an element is fullscreen. + * + * @module core/fullscreen + * @class fullscreen + * @package core + * @copyright 2020 University of Nottingham + * @author Neill Magill + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Gets the element that is fullscreen or null if no element is fullscreen. + * + * @returns {HTMLElement} + */ +export const getElement = () => { + let element = null; + if (document.fullscreenElement) { + element = document.fullscreenElement; + } else if (document.mozFullscreenElement) { + // Fallback for older Firefox. + element = document.mozFullscreenElement; + } else if (document.msFullscreenElement) { + // Fallback for Edge and IE. + element = document.msFullscreenElement; + } else if (document.webkitFullscreenElement) { + // Fallback for Chrome, Edge and Safari. + element = document.webkitFullscreenElement; + } + + return element; +}; diff --git a/lib/amd/src/modal.js b/lib/amd/src/modal.js index 37ce5746a22..3ca46d8a270 100644 --- a/lib/amd/src/modal.js +++ b/lib/amd/src/modal.js @@ -34,7 +34,21 @@ define([ 'core/local/aria/focuslock', 'core/pending', 'core/aria', -], function($, Templates, Notification, KeyCodes, CustomEvents, ModalBackdrop, Event, ModalEvents, FocusLock, Pending, Aria) { + 'core/fullscreen' +], function( + $, + Templates, + Notification, + KeyCodes, + CustomEvents, + ModalBackdrop, + Event, + ModalEvents, + FocusLock, + Pending, + Aria, + Fullscreen +) { var SELECTORS = { CONTAINER: '[data-region="modal-container"]', @@ -117,17 +131,20 @@ define([ }; /** - * Add the modal to the page, if it hasn't already been added. This includes running any + * Attach the modal to the correct part of the page. + * + * If it hasn't already been added it runs any * javascript that has been cached until now. * * @method attachToDOM */ Modal.prototype.attachToDOM = function() { + this.getAttachmentPoint().append(this.root); + if (this.isAttached) { return; } - $('body').append(this.root); FocusLock.trapFocus(this.root[0]); // If we'd cached any JS then we can run it how that the modal is @@ -625,6 +642,15 @@ define([ return this.getRoot().hasClass('fade'); }; + /** + * Gets the jQuery wrapped node that the Modal should be attached to. + * + * @returns {jQuery} + */ + Modal.prototype.getAttachmentPoint = function() { + return $(Fullscreen.getElement() || document.body); + }; + /** * Display this modal. The modal will be attached to the DOM if it hasn't * already been. @@ -645,9 +671,7 @@ define([ this.hideFooter(); } - if (!this.isAttached) { - this.attachToDOM(); - } + this.attachToDOM(); return this.getBackdrop() .then(function(backdrop) { @@ -689,6 +713,7 @@ define([ Modal.prototype.hide = function() { this.getBackdrop().done(function(backdrop) { FocusLock.untrapFocus(); + if (!this.countOtherVisibleModals()) { // Hide the backdrop if we're the last open modal. backdrop.hide(); @@ -710,6 +735,9 @@ define([ this.getRoot().removeClass('show').addClass('hide'); } + // Ensure the modal is moved onto the body node. + $(document.body).append(this.getRoot()); + this.root.trigger(ModalEvents.hidden, this); }.bind(this)); }; diff --git a/lib/amd/src/modal_backdrop.js b/lib/amd/src/modal_backdrop.js index 75a7b26a12b..9cc7448c3d2 100644 --- a/lib/amd/src/modal_backdrop.js +++ b/lib/amd/src/modal_backdrop.js @@ -22,8 +22,8 @@ * @copyright 2016 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define(['jquery', 'core/templates', 'core/notification'], - function($, Templates, Notification) { +define(['jquery', 'core/templates', 'core/notification', 'core/fullscreen'], + function($, Templates, Notification, Fullscreen) { var SELECTORS = { ROOT: '[data-region="modal-backdrop"]', @@ -53,17 +53,27 @@ define(['jquery', 'core/templates', 'core/notification'], return this.root; }; + /** + * Gets the jQuery wrapped node that the Modal should be attached to. + * + * @returns {jQuery} + */ + ModalBackdrop.prototype.getAttachmentPoint = function() { + return $(Fullscreen.getElement() || document.body); + }; + /** * Add the modal backdrop to the page, if it hasn't already been added. * * @method attachToDOM */ ModalBackdrop.prototype.attachToDOM = function() { + this.getAttachmentPoint().append(this.root); + if (this.isAttached) { return; } - $('body').append(this.root); this.isAttached = true; }; @@ -108,9 +118,7 @@ define(['jquery', 'core/templates', 'core/notification'], return; } - if (!this.isAttached) { - this.attachToDOM(); - } + this.attachToDOM(); this.root.removeClass('hide').addClass('show'); }; @@ -133,6 +141,9 @@ define(['jquery', 'core/templates', 'core/notification'], } else { this.getRoot().removeClass('show').addClass('hide'); } + + // Ensure the modal is moved back onto the body node. + $(document.body).append(this.getRoot()); }; /**