diff --git a/calendar/amd/build/crud.min.js b/calendar/amd/build/crud.min.js index d44cd944c8f..31d3420d683 100644 --- a/calendar/amd/build/crud.min.js +++ b/calendar/amd/build/crud.min.js @@ -1,2 +1,2 @@ -define ("core_calendar/crud",["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors","core/pending"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){function o(d,e,f){var i=[{key:"deleteevent",component:"calendar"}];f=parseInt(f,10);var m,o=1.\n\n/**\n * A module to handle CRUD operations within the UI.\n *\n * @module core_calendar/crud\n * @package core_calendar\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/modal_factory',\n 'core/modal_events',\n 'core_calendar/modal_event_form',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/modal_delete',\n 'core_calendar/selectors',\n 'core/pending',\n],\nfunction(\n $,\n Str,\n Notification,\n CustomEvents,\n Modal,\n ModalRegistry,\n ModalFactory,\n ModalEvents,\n ModalEventForm,\n CalendarRepository,\n CalendarEvents,\n ModalDelete,\n CalendarSelectors,\n Pending\n) {\n\n /**\n * Prepares the action for the summary modal's delete action.\n *\n * @param {Number} eventId The ID of the event.\n * @param {string} eventTitle The event title.\n * @param {Number} eventCount The number of events in the series.\n * @return {Promise}\n */\n function confirmDeletion(eventId, eventTitle, eventCount) {\n var deleteStrings = [\n {\n key: 'deleteevent',\n component: 'calendar'\n },\n ];\n\n eventCount = parseInt(eventCount, 10);\n var deletePromise;\n var isRepeatedEvent = eventCount > 1;\n if (isRepeatedEvent) {\n deleteStrings.push({\n key: 'confirmeventseriesdelete',\n component: 'calendar',\n param: {\n name: eventTitle,\n count: eventCount,\n },\n });\n\n deletePromise = ModalFactory.create(\n {\n type: ModalDelete.TYPE\n }\n );\n } else {\n deleteStrings.push({\n key: 'confirmeventdelete',\n component: 'calendar',\n param: eventTitle\n });\n\n\n deletePromise = ModalFactory.create(\n {\n type: ModalFactory.types.SAVE_CANCEL\n }\n );\n }\n\n var stringsPromise = Str.get_strings(deleteStrings);\n\n var finalPromise = $.when(stringsPromise, deletePromise)\n .then(function(strings, deleteModal) {\n deleteModal.setTitle(strings[0]);\n deleteModal.setBody(strings[1]);\n if (!isRepeatedEvent) {\n deleteModal.setSaveButtonText(strings[0]);\n }\n\n deleteModal.show();\n\n deleteModal.getRoot().on(ModalEvents.save, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedevent');\n CalendarRepository.deleteEvent(eventId, false)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, false]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n deleteModal.getRoot().on(CalendarEvents.deleteAll, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedallevent');\n CalendarRepository.deleteEvent(eventId, true)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, true]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n return deleteModal;\n })\n .catch(Notification.exception);\n\n return finalPromise;\n }\n\n /**\n * Create the event form modal for creating new events and\n * editing existing events.\n *\n * @method registerEventFormModal\n * @param {object} root The calendar root element\n * @return {object} The create modal promise\n */\n var registerEventFormModal = function(root) {\n var eventFormPromise = ModalFactory.create({\n type: ModalEventForm.TYPE,\n large: true\n });\n\n // Bind click event on the new event button.\n root.on('click', CalendarSelectors.actions.create, function(e) {\n eventFormPromise.then(function(modal) {\n var wrapper = root.find(CalendarSelectors.wrapper);\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n // Attempt to find the cell for today.\n // If it can't be found, then use the start time of the first day on the calendar.\n var today = root.find(CalendarSelectors.today);\n var firstDay = root.find(CalendarSelectors.day);\n if (!today.length && firstDay.length) {\n modal.setStartTime(firstDay.data('newEventTimestamp'));\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setCourseId(wrapper.data('courseid'));\n modal.show();\n return;\n })\n .fail(Notification.exception);\n\n e.preventDefault();\n });\n\n root.on('click', CalendarSelectors.actions.edit, function(e) {\n e.preventDefault();\n var target = $(e.currentTarget),\n calendarWrapper = target.closest(CalendarSelectors.wrapper),\n eventWrapper = target.closest(CalendarSelectors.eventItem);\n\n eventFormPromise.then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n modal.setEventId(eventWrapper.data('eventId'));\n\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n return;\n }).fail(Notification.exception);\n });\n\n\n return eventFormPromise;\n };\n /**\n * Register the listeners required to remove the event.\n *\n * @param {jQuery} root\n */\n function registerRemove(root) {\n root.on('click', CalendarSelectors.actions.remove, function(e) {\n // Fetch the event title, count, and pass them into the new dialogue.\n var eventSource = $(this).closest(CalendarSelectors.eventItem);\n var eventId = eventSource.data('eventId'),\n eventTitle = eventSource.data('eventTitle'),\n eventCount = eventSource.data('eventCount');\n confirmDeletion(eventId, eventTitle, eventCount);\n\n e.preventDefault();\n });\n }\n\n /**\n * Register the listeners required to edit the event.\n *\n * @param {jQuery} root\n * @param {Promise} eventFormModalPromise\n * @returns {Promise}\n */\n function registerEditListeners(root, eventFormModalPromise) {\n eventFormModalPromise\n .then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n $('body').on(CalendarEvents.editEvent, function(e, eventId) {\n var calendarWrapper = root.find(CalendarSelectors.wrapper);\n modal.setEventId(eventId);\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n });\n return;\n })\n .fail(Notification.exception);\n\n return eventFormModalPromise;\n }\n\n return {\n registerRemove: registerRemove,\n registerEditListeners: registerEditListeners,\n registerEventFormModal: registerEventFormModal\n };\n});\n"],"file":"crud.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/crud.js"],"names":["define","$","Str","Notification","CustomEvents","Modal","ModalRegistry","ModalFactory","ModalEvents","ModalEventForm","CalendarRepository","CalendarEvents","ModalDelete","CalendarSelectors","Pending","confirmDeletion","eventId","eventTitle","eventCount","pendingPromise","deleteStrings","key","component","parseInt","deletePromise","isRepeatedEvent","push","param","name","count","create","type","TYPE","types","SAVE_CANCEL","stringsPromise","get_strings","finalPromise","when","then","strings","deleteModal","setTitle","setBody","setSaveButtonText","show","getRoot","on","save","deleteEvent","trigger","deleted","resolve","catch","exception","deleteAll","modal","registerRemove","root","actions","remove","e","eventSource","closest","eventItem","data","preventDefault","registerEditListeners","eventFormModalPromise","editEvent","calendarWrapper","find","wrapper","setEventId","setContextId","stopImmediatePropagation","fail","registerEventFormModal","eventFormPromise","large","categoryId","setCategoryId","today","firstDay","day","length","setStartTime","setCourseId","edit","target","currentTarget","eventWrapper"],"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 * A module to handle CRUD operations within the UI.\n *\n * @module core_calendar/crud\n * @package core_calendar\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/modal_factory',\n 'core/modal_events',\n 'core_calendar/modal_event_form',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/modal_delete',\n 'core_calendar/selectors',\n 'core/pending',\n],\nfunction(\n $,\n Str,\n Notification,\n CustomEvents,\n Modal,\n ModalRegistry,\n ModalFactory,\n ModalEvents,\n ModalEventForm,\n CalendarRepository,\n CalendarEvents,\n ModalDelete,\n CalendarSelectors,\n Pending\n) {\n\n /**\n * Prepares the action for the summary modal's delete action.\n *\n * @param {Number} eventId The ID of the event.\n * @param {string} eventTitle The event title.\n * @param {Number} eventCount The number of events in the series.\n * @return {Promise}\n */\n function confirmDeletion(eventId, eventTitle, eventCount) {\n var pendingPromise = new Pending('core_calendar/crud:confirmDeletion');\n var deleteStrings = [\n {\n key: 'deleteevent',\n component: 'calendar'\n },\n ];\n\n eventCount = parseInt(eventCount, 10);\n var deletePromise;\n var isRepeatedEvent = eventCount > 1;\n if (isRepeatedEvent) {\n deleteStrings.push({\n key: 'confirmeventseriesdelete',\n component: 'calendar',\n param: {\n name: eventTitle,\n count: eventCount,\n },\n });\n\n deletePromise = ModalFactory.create(\n {\n type: ModalDelete.TYPE\n }\n );\n } else {\n deleteStrings.push({\n key: 'confirmeventdelete',\n component: 'calendar',\n param: eventTitle\n });\n\n\n deletePromise = ModalFactory.create(\n {\n type: ModalFactory.types.SAVE_CANCEL\n }\n );\n }\n\n var stringsPromise = Str.get_strings(deleteStrings);\n\n var finalPromise = $.when(stringsPromise, deletePromise)\n .then(function(strings, deleteModal) {\n deleteModal.setTitle(strings[0]);\n deleteModal.setBody(strings[1]);\n if (!isRepeatedEvent) {\n deleteModal.setSaveButtonText(strings[0]);\n }\n\n deleteModal.show();\n\n deleteModal.getRoot().on(ModalEvents.save, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedevent');\n CalendarRepository.deleteEvent(eventId, false)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, false]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n deleteModal.getRoot().on(CalendarEvents.deleteAll, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedallevent');\n CalendarRepository.deleteEvent(eventId, true)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, true]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n return deleteModal;\n })\n .then(function(modal) {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n\n return finalPromise;\n }\n\n /**\n * Create the event form modal for creating new events and\n * editing existing events.\n *\n * @method registerEventFormModal\n * @param {object} root The calendar root element\n * @return {object} The create modal promise\n */\n var registerEventFormModal = function(root) {\n var eventFormPromise = ModalFactory.create({\n type: ModalEventForm.TYPE,\n large: true\n });\n\n // Bind click event on the new event button.\n root.on('click', CalendarSelectors.actions.create, function(e) {\n eventFormPromise.then(function(modal) {\n var wrapper = root.find(CalendarSelectors.wrapper);\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n // Attempt to find the cell for today.\n // If it can't be found, then use the start time of the first day on the calendar.\n var today = root.find(CalendarSelectors.today);\n var firstDay = root.find(CalendarSelectors.day);\n if (!today.length && firstDay.length) {\n modal.setStartTime(firstDay.data('newEventTimestamp'));\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setCourseId(wrapper.data('courseid'));\n modal.show();\n return;\n })\n .fail(Notification.exception);\n\n e.preventDefault();\n });\n\n root.on('click', CalendarSelectors.actions.edit, function(e) {\n e.preventDefault();\n var target = $(e.currentTarget),\n calendarWrapper = target.closest(CalendarSelectors.wrapper),\n eventWrapper = target.closest(CalendarSelectors.eventItem);\n\n eventFormPromise.then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n modal.setEventId(eventWrapper.data('eventId'));\n\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n return;\n }).fail(Notification.exception);\n });\n\n\n return eventFormPromise;\n };\n /**\n * Register the listeners required to remove the event.\n *\n * @param {jQuery} root\n */\n function registerRemove(root) {\n root.on('click', CalendarSelectors.actions.remove, function(e) {\n // Fetch the event title, count, and pass them into the new dialogue.\n var eventSource = $(this).closest(CalendarSelectors.eventItem);\n var eventId = eventSource.data('eventId'),\n eventTitle = eventSource.data('eventTitle'),\n eventCount = eventSource.data('eventCount');\n confirmDeletion(eventId, eventTitle, eventCount);\n\n e.preventDefault();\n });\n }\n\n /**\n * Register the listeners required to edit the event.\n *\n * @param {jQuery} root\n * @param {Promise} eventFormModalPromise\n * @returns {Promise}\n */\n function registerEditListeners(root, eventFormModalPromise) {\n eventFormModalPromise\n .then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n $('body').on(CalendarEvents.editEvent, function(e, eventId) {\n var calendarWrapper = root.find(CalendarSelectors.wrapper);\n modal.setEventId(eventId);\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n });\n return;\n })\n .fail(Notification.exception);\n\n return eventFormModalPromise;\n }\n\n return {\n registerRemove: registerRemove,\n registerEditListeners: registerEditListeners,\n registerEventFormModal: registerEventFormModal\n };\n});\n"],"file":"crud.min.js"} \ No newline at end of file diff --git a/calendar/amd/build/modal_delete.min.js b/calendar/amd/build/modal_delete.min.js index 184a2836c39..77dbc028a3a 100644 --- a/calendar/amd/build/modal_delete.min.js +++ b/calendar/amd/build/modal_delete.min.js @@ -1,2 +1,2 @@ -define ("core_calendar/modal_delete",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events","core/modal_registry","core_calendar/events"],function(a,b,c,d,f,g,h){var i=!1,j={DELETE_ONE_BUTTON:"[data-action=\"deleteone\"]",DELETE_ALL_BUTTON:"[data-action=\"deleteall\"]",CANCEL_BUTTON:"[data-action=\"cancel\"]"},k=function(a){d.call(this,a)};k.TYPE="core_calendar-modal_delete";k.prototype=Object.create(d.prototype);k.prototype.constructor=k;k.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this);this.getModal().on(c.events.activate,j.DELETE_ONE_BUTTON,function(b,c){var d=a.Event(f.save);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,j.DELETE_ALL_BUTTON,function(b,c){var d=a.Event(h.deleteAll);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,j.CANCEL_BUTTON,function(b,c){var d=a.Event(f.cancel);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this))};if(!i){g.register(k.TYPE,k,"calendar/event_delete_modal");i=!0}return k}); +define ("core_calendar/modal_delete",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events","core/modal_registry","core_calendar/events"],function(a,b,c,d,f,g,h){var i=!1,j={DELETE_ONE_BUTTON:"[data-action=\"deleteone\"]",DELETE_ALL_BUTTON:"[data-action=\"deleteall\"]",CANCEL_BUTTON:"[data-action=\"cancel\"]"},k=function(a){d.call(this,a);this.setRemoveOnClose(!0)};k.TYPE="core_calendar-modal_delete";k.prototype=Object.create(d.prototype);k.prototype.constructor=k;k.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this);this.getModal().on(c.events.activate,j.DELETE_ONE_BUTTON,function(b,c){var d=a.Event(f.save);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,j.DELETE_ALL_BUTTON,function(b,c){var d=a.Event(h.deleteAll);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,j.CANCEL_BUTTON,function(b,c){var d=a.Event(f.cancel);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this))};if(!i){g.register(k.TYPE,k,"calendar/event_delete_modal");i=!0}return k}); //# sourceMappingURL=modal_delete.min.js.map diff --git a/calendar/amd/build/modal_delete.min.js.map b/calendar/amd/build/modal_delete.min.js.map index 4a4c1857b15..090c326af6b 100644 --- a/calendar/amd/build/modal_delete.min.js.map +++ b/calendar/amd/build/modal_delete.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/modal_delete.js"],"names":["define","$","Notification","CustomEvents","Modal","ModalEvents","ModalRegistry","CalendarEvents","registered","SELECTORS","DELETE_ONE_BUTTON","DELETE_ALL_BUTTON","CANCEL_BUTTON","ModalDelete","root","call","TYPE","prototype","Object","create","constructor","registerEventListeners","getModal","on","events","activate","e","data","saveEvent","Event","save","getRoot","trigger","isDefaultPrevented","hide","originalEvent","preventDefault","bind","deleteAll","cancelEvent","cancel","register"],"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 the save/cancel modal.\n *\n * @module core_calendar/modal_delete\n * @class modal_delete\n * @package core_calendar\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_events',\n 'core/modal_registry',\n 'core_calendar/events',\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Modal,\n ModalEvents,\n ModalRegistry,\n CalendarEvents\n) {\n\n var registered = false;\n var SELECTORS = {\n DELETE_ONE_BUTTON: '[data-action=\"deleteone\"]',\n DELETE_ALL_BUTTON: '[data-action=\"deleteall\"]',\n CANCEL_BUTTON: '[data-action=\"cancel\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalDelete = function(root) {\n Modal.call(this, root);\n };\n\n ModalDelete.TYPE = 'core_calendar-modal_delete';\n ModalDelete.prototype = Object.create(Modal.prototype);\n ModalDelete.prototype.constructor = ModalDelete;\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalDelete.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ONE_BUTTON, function(e, data) {\n var saveEvent = $.Event(ModalEvents.save);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ALL_BUTTON, function(e, data) {\n var saveEvent = $.Event(CalendarEvents.deleteAll);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) {\n var cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalDelete.TYPE, ModalDelete, 'calendar/event_delete_modal');\n registered = true;\n }\n\n return ModalDelete;\n});\n"],"file":"modal_delete.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/modal_delete.js"],"names":["define","$","Notification","CustomEvents","Modal","ModalEvents","ModalRegistry","CalendarEvents","registered","SELECTORS","DELETE_ONE_BUTTON","DELETE_ALL_BUTTON","CANCEL_BUTTON","ModalDelete","root","call","setRemoveOnClose","TYPE","prototype","Object","create","constructor","registerEventListeners","getModal","on","events","activate","e","data","saveEvent","Event","save","getRoot","trigger","isDefaultPrevented","hide","originalEvent","preventDefault","bind","deleteAll","cancelEvent","cancel","register"],"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 the save/cancel modal.\n *\n * @module core_calendar/modal_delete\n * @class modal_delete\n * @package core_calendar\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_events',\n 'core/modal_registry',\n 'core_calendar/events',\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Modal,\n ModalEvents,\n ModalRegistry,\n CalendarEvents\n) {\n\n var registered = false;\n var SELECTORS = {\n DELETE_ONE_BUTTON: '[data-action=\"deleteone\"]',\n DELETE_ALL_BUTTON: '[data-action=\"deleteall\"]',\n CANCEL_BUTTON: '[data-action=\"cancel\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalDelete = function(root) {\n Modal.call(this, root);\n\n this.setRemoveOnClose(true);\n };\n\n ModalDelete.TYPE = 'core_calendar-modal_delete';\n ModalDelete.prototype = Object.create(Modal.prototype);\n ModalDelete.prototype.constructor = ModalDelete;\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalDelete.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ONE_BUTTON, function(e, data) {\n var saveEvent = $.Event(ModalEvents.save);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ALL_BUTTON, function(e, data) {\n var saveEvent = $.Event(CalendarEvents.deleteAll);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) {\n var cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalDelete.TYPE, ModalDelete, 'calendar/event_delete_modal');\n registered = true;\n }\n\n return ModalDelete;\n});\n"],"file":"modal_delete.min.js"} \ No newline at end of file diff --git a/calendar/amd/src/crud.js b/calendar/amd/src/crud.js index 7853a67fdea..c18cb567285 100644 --- a/calendar/amd/src/crud.js +++ b/calendar/amd/src/crud.js @@ -63,6 +63,7 @@ function( * @return {Promise} */ function confirmDeletion(eventId, eventTitle, eventCount) { + var pendingPromise = new Pending('core_calendar/crud:confirmDeletion'); var deleteStrings = [ { key: 'deleteevent', @@ -139,6 +140,11 @@ function( return deleteModal; }) + .then(function(modal) { + pendingPromise.resolve(); + + return modal; + }) .catch(Notification.exception); return finalPromise; diff --git a/calendar/amd/src/modal_delete.js b/calendar/amd/src/modal_delete.js index 9541dec35e2..e457761ef78 100644 --- a/calendar/amd/src/modal_delete.js +++ b/calendar/amd/src/modal_delete.js @@ -55,6 +55,8 @@ function( */ var ModalDelete = function(root) { Modal.call(this, root); + + this.setRemoveOnClose(true); }; ModalDelete.TYPE = 'core_calendar-modal_delete'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index f0a53e98018..4885cc4598e 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -1499,6 +1499,7 @@ $string['numwords'] = '{$a} words'; $string['numyear'] = '{$a} year'; $string['numyears'] = '{$a} years'; $string['ok'] = 'OK'; +$string['okay'] = 'Ok'; $string['oldpassword'] = 'Current password'; $string['olduserdirectory'] = 'This is the OLD users directory, and is no longer needed. You may safely delete it. The files it contains have been copied to the NEW user directory.'; $string['optional'] = 'optional'; diff --git a/lib/amd/build/local/modal/alert.min.js b/lib/amd/build/local/modal/alert.min.js new file mode 100644 index 00000000000..83441633d45 --- /dev/null +++ b/lib/amd/build/local/modal/alert.min.js @@ -0,0 +1,2 @@ +define ("core/local/modal/alert",["exports","core/modal"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function c(a){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;c.\n\n/**\n * Alert modal.\n *\n * @module core/modal_alert\n * @class modal_alert\n * @package core\n * @copyright 2020 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\n\nexport default class extends Modal {\n /**\n * Register all event listeners.\n */\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on cancel.\n this.registerCloseOnCancel();\n }\n}\n"],"file":"alert.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 3269e6e7d7b..642c2ed7ccd 100644 --- a/lib/amd/build/modal.min.js +++ b/lib/amd/build/modal.min.js @@ -1,2 +1,2 @@ -function _typeof(a){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"],function(a,b,c,d,e,f,g,h,i,j){var k={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]"},l={LOADING:"core/loading",BACKDROP:"core/modal_backdrop"},m,n=0,o=function(b){this.root=a(b);this.modal=this.root.find(k.MODAL);this.header=this.modal.find(k.HEADER);this.headerPromise=a.Deferred();this.title=this.header.find(k.TITLE);this.titlePromise=a.Deferred();this.body=this.modal.find(k.BODY);this.bodyPromise=a.Deferred();this.footer=this.modal.find(k.FOOTER);this.footerPromise=a.Deferred();this.hiddenSiblings=[];this.isAttached=!1;this.bodyJS=null;this.footerJS=null;this.modalCount=n++;if(!this.root.is(k.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()};o.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};o.prototype.countOtherVisibleModals=function(){var b=0;a("body").find(k.CONTAINER).each(function(c,d){d=a(d);if(!this.root.is(d)&&d.hasClass("show")){b++}}.bind(this));return b};o.prototype.getBackdrop=function(){if(!m){m=b.render(l.BACKDROP,{}).then(function(b){var c=a(b);return new f(c)}).fail(c.exception)}return m};o.prototype.getRoot=function(){return this.root};o.prototype.getModal=function(){return this.modal};o.prototype.getTitle=function(){return this.title};o.prototype.getBody=function(){return this.body};o.prototype.getFooter=function(){return this.footer};o.prototype.getTitlePromise=function(){return this.titlePromise};o.prototype.getBodyPromise=function(){return this.bodyPromise};o.prototype.getFooterPromise=function(){return this.footerPromise};o.prototype.getModalCount=function(){return this.modalCount};o.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)};o.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");if("pending"==d.state()){var j=e.innerHeight();if(100>j){j=100}e.animate({height:j+"px"},150);e.html("");i=b.render(l.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)}};o.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(l.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)}};o.prototype.hasFooterContent=function(){return this.getFooter().children().length?!0:!1};o.prototype.hideFooter=function(){this.getFooter().addClass("hidden")};o.prototype.showFooter=function(){this.getFooter().removeClass("hidden")};o.prototype.setLarge=function(){if(this.isLarge()){return}this.getModal().addClass("modal-lg")};o.prototype.isLarge=function(){return this.getModal().hasClass("modal-lg")};o.prototype.setSmall=function(){if(this.isSmall()){return}this.getModal().removeClass("modal-lg")};o.prototype.isSmall=function(){return!this.getModal().hasClass("modal-lg")};o.prototype.calculateZIndex=function(){var b=a(k.DIALOG+", "+k.MENU_BAR+", "+k.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};o.prototype.isVisible=function(){return this.root.hasClass("show")};o.prototype.hasFocus=function(){var b=a(document.activeElement);return this.root.is(b)||this.root.has(b).length};o.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")};o.prototype.show=function(){if(this.isVisible()){return}var b=new j("core/modal:show");if(this.hasFooterContent()){this.showFooter()}else{this.hideFooter()}if(!this.isAttached){this.attachToDOM()}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)};o.prototype.hideIfNotForm=function(){var a=this.modal.find(k.FORM);if(0==a.length){this.hide()}};o.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))};o.prototype.destroy=function(){this.root.remove();this.root.trigger(h.destroyed,this)};o.prototype.accessibilityShow=function(){a("body").children().each(function(b,c){if(!this.root.is(c)){c=a(c);var d=c.attr("aria-hidden");if("true"!==d){c.data("previous-aria-hidden",d);this.hiddenSiblings.push(c);c.attr("aria-hidden","true")}}}.bind(this));this.root.attr("aria-hidden","false")};o.prototype.accessibilityHide=function(){this.root.attr("aria-hidden","true");a.each(this.hiddenSiblings,function(b,c){c=a(c);var d=c.data("previous-aria-hidden");if("undefined"==typeof d){c.removeAttr("aria-hidden")}else{c.attr("aria-hidden",d)}});this.hiddenSiblings=[]};o.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(k.MODAL).length){if(a(b.target).closest(k.CONTAINER).length){this.hideIfNotForm()}}}.bind(this));e.define(this.getModal(),[e.events.activate]);this.getModal().on(e.events.activate,k.HIDE,function(a,b){this.hide();b.originalEvent.preventDefault()}.bind(this))};o.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};return o}); +function _typeof(a){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"],function(a,b,c,d,e,f,g,h,i,j){var k={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]"},l={LOADING:"core/loading",BACKDROP:"core/modal_backdrop"},m,n=0,o=function(b){this.root=a(b);this.modal=this.root.find(k.MODAL);this.header=this.modal.find(k.HEADER);this.headerPromise=a.Deferred();this.title=this.header.find(k.TITLE);this.titlePromise=a.Deferred();this.body=this.modal.find(k.BODY);this.bodyPromise=a.Deferred();this.footer=this.modal.find(k.FOOTER);this.footerPromise=a.Deferred();this.hiddenSiblings=[];this.isAttached=!1;this.bodyJS=null;this.footerJS=null;this.modalCount=n++;if(!this.root.is(k.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()};o.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};o.prototype.countOtherVisibleModals=function(){var b=0;a("body").find(k.CONTAINER).each(function(c,d){d=a(d);if(!this.root.is(d)&&d.hasClass("show")){b++}}.bind(this));return b};o.prototype.getBackdrop=function(){if(!m){m=b.render(l.BACKDROP,{}).then(function(b){var c=a(b);return new f(c)}).fail(c.exception)}return m};o.prototype.getRoot=function(){return this.root};o.prototype.getModal=function(){return this.modal};o.prototype.getTitle=function(){return this.title};o.prototype.getBody=function(){return this.body};o.prototype.getFooter=function(){return this.footer};o.prototype.getTitlePromise=function(){return this.titlePromise};o.prototype.getBodyPromise=function(){return this.bodyPromise};o.prototype.getFooterPromise=function(){return this.footerPromise};o.prototype.getModalCount=function(){return this.modalCount};o.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)};o.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");if("pending"==d.state()){var j=e.innerHeight();if(100>j){j=100}e.animate({height:j+"px"},150);e.html("");i=b.render(l.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)}};o.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(l.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)}};o.prototype.hasFooterContent=function(){return this.getFooter().children().length?!0:!1};o.prototype.hideFooter=function(){this.getFooter().addClass("hidden")};o.prototype.showFooter=function(){this.getFooter().removeClass("hidden")};o.prototype.setLarge=function(){if(this.isLarge()){return}this.getModal().addClass("modal-lg")};o.prototype.isLarge=function(){return this.getModal().hasClass("modal-lg")};o.prototype.setSmall=function(){if(this.isSmall()){return}this.getModal().removeClass("modal-lg")};o.prototype.isSmall=function(){return!this.getModal().hasClass("modal-lg")};o.prototype.calculateZIndex=function(){var b=a(k.DIALOG+", "+k.MENU_BAR+", "+k.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};o.prototype.isVisible=function(){return this.root.hasClass("show")};o.prototype.hasFocus=function(){var b=a(document.activeElement);return this.root.is(b)||this.root.has(b).length};o.prototype.hasTransitions=function(){return this.getRoot().hasClass("fade")};o.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)};o.prototype.hideIfNotForm=function(){var a=this.modal.find(k.FORM);if(0==a.length){this.hide()}};o.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))};o.prototype.destroy=function(){this.hide();this.root.remove();this.root.trigger(h.destroyed,this)};o.prototype.accessibilityShow=function(){a("body").children().each(function(b,c){if(!this.root.is(c)){c=a(c);var d=c.attr("aria-hidden");if("true"!==d){c.data("previous-aria-hidden",d);this.hiddenSiblings.push(c);c.attr("aria-hidden","true")}}}.bind(this));this.root.attr("aria-hidden","false")};o.prototype.accessibilityHide=function(){this.root.attr("aria-hidden","true");a.each(this.hiddenSiblings,function(b,c){c=a(c);var d=c.data("previous-aria-hidden");if("undefined"==typeof d){c.removeAttr("aria-hidden")}else{c.attr("aria-hidden",d)}});this.hiddenSiblings=[]};o.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(k.MODAL).length){if(a(b.target).closest(k.CONTAINER).length){this.hideIfNotForm()}}}.bind(this));e.define(this.getModal(),[e.events.activate]);this.getModal().on(e.events.activate,k.HIDE,function(a,b){this.hide();b.originalEvent.preventDefault()}.bind(this))};o.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))};o.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))};o.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};o.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))};o.prototype.getActionSelector=function(a){return"[data-action='"+a+"']"};o.prototype.setRemoveOnClose=function(a){this.removeOnClose=a};return o}); //# sourceMappingURL=modal.min.js.map diff --git a/lib/amd/build/modal.min.js.map b/lib/amd/build/modal.min.js.map index 5b24706db59..cb5d00f1c77 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","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","state","height","innerHeight","animate","loadingIcon","hide","fadeIn","when","promise","fadeOut","js","result","isVisible","currentHeight","newHeight","opacity","duration","queue","always","js_complete","setFooter","showFooter","hasFooterContent","children","hideFooter","addClass","removeClass","setLarge","isLarge","setSmall","isSmall","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","remove","destroyed","child","attr","data","push","sibling","previousValue","removeAttr","on","e","keyCode","escape","click","closest","events","activate","originalEvent","preventDefault","setFunction","p","hasOwnProperty","content"],"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], function($, Templates, Notification, KeyCodes, CustomEvents, ModalBackdrop, Event, ModalEvents, FocusLock, Pending) {\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 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 * 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 */\n Modal.prototype.show = function() {\n if (this.isVisible()) {\n return;\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 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.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 // We need to get a list containing each sibling element and the shallowest\n // non-ancestral nodes in the DOM. We can shortcut this a little by leveraging\n // the fact that this dialogue is always appended to the document body therefore\n // it's siblings are the shallowest non-ancestral nodes. If that changes then\n // this code should also be updated.\n $('body').children().each(function(index, child) {\n // Skip the current modal.\n if (!this.root.is(child)) {\n child = $(child);\n var hidden = child.attr('aria-hidden');\n // If they are already hidden we can ignore them.\n if (hidden !== 'true') {\n // Save their current state.\n child.data('previous-aria-hidden', hidden);\n this.hiddenSiblings.push(child);\n\n // Hide this node from screen readers.\n child.attr('aria-hidden', 'true');\n }\n }\n }.bind(this));\n\n // Make us visible to screen readers.\n this.root.attr('aria-hidden', 'false');\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 this.root.attr('aria-hidden', 'true');\n\n // Restore the sibling nodes back to their original values.\n $.each(this.hiddenSiblings, function(index, sibling) {\n sibling = $(sibling);\n var previousValue = sibling.data('previous-aria-hidden');\n // If the element didn't previously have an aria-hidden attribute\n // then we can just remove the one we set.\n if (typeof previousValue == 'undefined') {\n sibling.removeAttr('aria-hidden');\n } else {\n // Otherwise set it back to the old value (which will be false).\n sibling.attr('aria-hidden', previousValue);\n }\n });\n\n // Clear the cache. No longer need to store these.\n this.hiddenSiblings = [];\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 this.hideIfNotForm();\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 * 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 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","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","state","height","innerHeight","animate","loadingIcon","hide","fadeIn","when","promise","fadeOut","js","result","isVisible","currentHeight","newHeight","opacity","duration","queue","always","js_complete","setFooter","showFooter","hasFooterContent","children","hideFooter","addClass","removeClass","setLarge","isLarge","setSmall","isSmall","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","remove","destroyed","child","attr","data","push","sibling","previousValue","removeAttr","on","e","keyCode","escape","click","closest","events","activate","originalEvent","preventDefault","registerCloseOnCancel","getActionSelector","cancelEvent","cancel","isDefaultPrevented","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], function($, Templates, Notification, KeyCodes, CustomEvents, ModalBackdrop, Event, ModalEvents, FocusLock, Pending) {\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 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 * 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 // We need to get a list containing each sibling element and the shallowest\n // non-ancestral nodes in the DOM. We can shortcut this a little by leveraging\n // the fact that this dialogue is always appended to the document body therefore\n // it's siblings are the shallowest non-ancestral nodes. If that changes then\n // this code should also be updated.\n $('body').children().each(function(index, child) {\n // Skip the current modal.\n if (!this.root.is(child)) {\n child = $(child);\n var hidden = child.attr('aria-hidden');\n // If they are already hidden we can ignore them.\n if (hidden !== 'true') {\n // Save their current state.\n child.data('previous-aria-hidden', hidden);\n this.hiddenSiblings.push(child);\n\n // Hide this node from screen readers.\n child.attr('aria-hidden', 'true');\n }\n }\n }.bind(this));\n\n // Make us visible to screen readers.\n this.root.attr('aria-hidden', 'false');\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 this.root.attr('aria-hidden', 'true');\n\n // Restore the sibling nodes back to their original values.\n $.each(this.hiddenSiblings, function(index, sibling) {\n sibling = $(sibling);\n var previousValue = sibling.data('previous-aria-hidden');\n // If the element didn't previously have an aria-hidden attribute\n // then we can just remove the one we set.\n if (typeof previousValue == 'undefined') {\n sibling.removeAttr('aria-hidden');\n } else {\n // Otherwise set it back to the old value (which will be false).\n sibling.attr('aria-hidden', previousValue);\n }\n });\n\n // Clear the cache. No longer need to store these.\n this.hiddenSiblings = [];\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 this.hideIfNotForm();\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_cancel.min.js b/lib/amd/build/modal_cancel.min.js index c172543552d..90366c2fb4e 100644 --- a/lib/amd/build/modal_cancel.min.js +++ b/lib/amd/build/modal_cancel.min.js @@ -1,2 +1,2 @@ -define ("core/modal_cancel",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events"],function(a,b,c,d,f){var g={CANCEL_BUTTON:"[data-action=\"cancel\"]"},h=function(a){d.call(this,a);if(!this.getFooter().find(g.CANCEL_BUTTON).length){b.exception({message:"No cancel button found"})}};h.prototype=Object.create(d.prototype);h.prototype.constructor=h;h.prototype.setFooter=function(){b.exception({message:"Can not change the footer of a cancel modal"})};h.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this);this.getModal().on(c.events.activate,g.CANCEL_BUTTON,function(b,c){var d=a.Event(f.cancel);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this))};return h}); +define ("core/modal_cancel",["exports","core/modal"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function c(a){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;c.\n\n/**\n * Contain the logic for the cancel modal.\n *\n * @module core/modal_cancel\n * @class modal_cancel\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/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_events'],\n function($, Notification, CustomEvents, Modal, ModalEvents) {\n\n var SELECTORS = {\n CANCEL_BUTTON: '[data-action=\"cancel\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalCancel = function(root) {\n Modal.call(this, root);\n\n if (!this.getFooter().find(SELECTORS.CANCEL_BUTTON).length) {\n Notification.exception({message: 'No cancel button found'});\n }\n };\n\n ModalCancel.prototype = Object.create(Modal.prototype);\n ModalCancel.prototype.constructor = ModalCancel;\n\n /**\n * Override parent implementation to prevent changing the footer content.\n */\n ModalCancel.prototype.setFooter = function() {\n Notification.exception({message: 'Can not change the footer of a cancel modal'});\n return;\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalCancel.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) {\n var cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n return ModalCancel;\n});\n"],"file":"modal_cancel.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/modal_cancel.js"],"names":["root","getFooter","find","getActionSelector","length","Notification","exception","message","registerCloseOnCancel","Modal"],"mappings":"kJAwBA,uD,gjDAGI,WAAYA,CAAZ,CAAkB,iBACd,wBAAMA,CAAN,GAEA,GAAI,CAAC,EAAKC,SAAL,GAAiBC,IAAjB,CAAsB,EAAKC,iBAAL,CAAuB,QAAvB,CAAtB,EAAwDC,MAA7D,CAAqE,CACjEC,YAAY,CAACC,SAAb,CAAuB,CAACC,OAAO,CAAE,wBAAV,CAAvB,CACH,CALa,QAMjB,C,0EAKwB,CAErB,2DAGA,KAAKC,qBAAL,EACH,C,cAlBwBC,S","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 the cancel modal.\n *\n * @module core/modal_cancel\n * @class modal_cancel\n * @package core\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Modal from 'core/modal';\n\nexport default class extends Modal {\n constructor(root) {\n super(root);\n\n if (!this.getFooter().find(this.getActionSelector('cancel')).length) {\n Notification.exception({message: 'No cancel button found'});\n }\n }\n\n /**\n * Register all event listeners.\n */\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on cancel.\n this.registerCloseOnCancel();\n }\n}\n"],"file":"modal_cancel.min.js"} \ No newline at end of file diff --git a/lib/amd/build/modal_factory.min.js b/lib/amd/build/modal_factory.min.js index 2fa4d54f33d..87e5370af77 100644 --- a/lib/amd/build/modal_factory.min.js +++ b/lib/amd/build/modal_factory.min.js @@ -1,2 +1,2 @@ -define ("core/modal_factory",["jquery","core/modal_events","core/modal_registry","core/modal","core/modal_save_cancel","core/modal_cancel","core/templates","core/notification","core/custom_interaction_events","core/pending"],function(a,b,c,d,e,f,g,h,i,j){var k={DEFAULT:"core/modal",SAVE_CANCEL:"core/modal_save_cancel",CANCEL:"core/modal_cancel"},l={DEFAULT:"DEFAULT",SAVE_CANCEL:"SAVE_CANCEL",CANCEL:"CANCEL"};c.register(l.DEFAULT,d,k.DEFAULT);c.register(l.SAVE_CANCEL,e,k.SAVE_CANCEL);c.register(l.CANCEL,f,k.CANCEL);var m=function(c,d,e){var f=null,g="function"==typeof e.preShowCallback,h=function(b,d){var h=new j("core/modal_factory:setUpTrigger:triggeredCallback");f=a(b.currentTarget);c.then(function(a){if(g){e.preShowCallback(f,a)}a.show();return a}).then(h.resolve);d.originalEvent.preventDefault()};if(Array.isArray(d)){var k=d[1];d=d[0];i.define(d,[i.events.activate]);d.on(i.events.activate,k,h)}else{i.define(d,[i.events.activate]);d.on(i.events.activate,h)}c.then(function(a){a.getRoot().on(b.hidden,function(){if(null!==f){f.focus()}});return a})},n=function(b,c){c=a(c);var d=b.module,e=new d(c);return e},o=function(b,c){var d=b.template,e=g.render(d,c).then(function(c){var d=a(c);return n(b,d)}).fail(h.exception);return e};return{create:function create(a,b){var d=a.type||l.DEFAULT,e=a.large?!0:!1,f=null,g={};f=c.get(d);if(!f){h.exception({message:"Unable to find modal of type: "+d})}if("undefined"!=typeof a.templateContext){g=a.templateContext}var i=o(f,g).then(function(b){if("undefined"!=typeof a.title){b.setTitle(a.title)}if("undefined"!=typeof a.body){b.setBody(a.body)}if("undefined"!=typeof a.footer){b.setFooter(a.footer)}if(e){b.setLarge()}return b});if("undefined"!=typeof b){m(i,b,a)}return i},types:l}}); +function _slicedToArray(a,b){return _arrayWithHoles(a)||_iterableToArrayLimit(a,b)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}function _iterableToArrayLimit(a,b){var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function _arrayWithHoles(a){if(Array.isArray(a))return a}define ("core/modal_factory",["jquery","core/modal_events","core/modal_registry","core/modal","core/modal_save_cancel","core/modal_cancel","core/local/modal/alert","core/templates","core/notification","core/custom_interaction_events","core/pending"],function(a,b,c,d,e,f,g,h,i,j,k){var l={DEFAULT:"core/modal",SAVE_CANCEL:"core/modal_save_cancel",CANCEL:"core/modal_cancel",ALERT:"core/local/modal/alert"},m={DEFAULT:"DEFAULT",SAVE_CANCEL:"SAVE_CANCEL",CANCEL:"CANCEL",ALERT:"ALERT"};c.register(m.DEFAULT,d,l.DEFAULT);c.register(m.SAVE_CANCEL,e,l.SAVE_CANCEL);c.register(m.CANCEL,f,l.CANCEL);c.register(m.ALERT,g,l.ALERT);var n=function(c,d,e){var f=null,g="function"==typeof e.preShowCallback,h=function(b,d){var h=new k("core/modal_factory:setUpTrigger:triggeredCallback");f=a(b.currentTarget);c.then(function(a){if(g){e.preShowCallback(f,a)}a.show();return a}).then(h.resolve);d.originalEvent.preventDefault()};if(Array.isArray(d)){var i=d[1];d=d[0];j.define(d,[j.events.activate]);d.on(j.events.activate,i,h)}else{j.define(d,[j.events.activate]);d.on(j.events.activate,h)}c.then(function(a){a.getRoot().on(b.hidden,function(){if(null!==f){f.focus()}});return a})},o=function(b,c){c=a(c);var d=b.module,e=new d(c);return e},p=function(b,c){var d=b.template,e=h.render(d,c).then(function(c){var d=a(c);return o(b,d)}).fail(i.exception);return e};return{create:function create(a,b){var d=a.type||m.DEFAULT,e=a.large?!0:!1,f=null,g={};f=c.get(d);if(!f){i.exception({message:"Unable to find modal of type: "+d})}if("undefined"!=typeof a.templateContext){g=a.templateContext}var h=p(f,g).then(function(b){if("undefined"!=typeof a.title){b.setTitle(a.title)}if("undefined"!=typeof a.body){b.setBody(a.body)}if("undefined"!=typeof a.footer){b.setFooter(a.footer)}if(a.buttons){Object.entries(a.buttons).forEach(function(a){var c=_slicedToArray(a,2),d=c[0],e=c[1];b.setButtonText(d,e)})}if(e){b.setLarge()}if("undefined"!=typeof a.removeOnClose){b.setRemoveOnClose(a.removeOnClose)}return b});if("undefined"!=typeof b){n(h,b,a)}return h},types:m}}); //# sourceMappingURL=modal_factory.min.js.map diff --git a/lib/amd/build/modal_factory.min.js.map b/lib/amd/build/modal_factory.min.js.map index ff93873faf3..5d1aafdf254 100644 --- a/lib/amd/build/modal_factory.min.js.map +++ b/lib/amd/build/modal_factory.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/modal_factory.js"],"names":["define","$","ModalEvents","ModalRegistry","Modal","ModalSaveCancel","ModalCancel","Templates","Notification","CustomEvents","Pending","TEMPLATES","DEFAULT","SAVE_CANCEL","CANCEL","TYPES","register","setUpTrigger","modalPromise","triggerElement","modalConfig","actualTriggerElement","hasPreShowCallback","preShowCallback","triggeredCallback","e","data","pendingPromise","currentTarget","then","modal","show","resolve","originalEvent","preventDefault","Array","isArray","selector","events","activate","on","getRoot","hidden","focus","createFromElement","registryConf","modalElement","module","createFromType","templateContext","templateName","template","render","html","fail","exception","create","type","isLarge","large","get","message","title","setTitle","body","setBody","footer","setFooter","setLarge","types"],"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 * Create a modal.\n *\n * @module core/modal_factory\n * @class modal_factory\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/modal_events', 'core/modal_registry', 'core/modal',\n 'core/modal_save_cancel', 'core/modal_cancel',\n 'core/templates', 'core/notification', 'core/custom_interaction_events',\n 'core/pending'],\n function($, ModalEvents, ModalRegistry, Modal, ModalSaveCancel,\n ModalCancel, Templates, Notification, CustomEvents, Pending) {\n\n // The templates for each type of modal.\n var TEMPLATES = {\n DEFAULT: 'core/modal',\n SAVE_CANCEL: 'core/modal_save_cancel',\n CANCEL: 'core/modal_cancel',\n };\n\n // The available types of modals.\n var TYPES = {\n DEFAULT: 'DEFAULT',\n SAVE_CANCEL: 'SAVE_CANCEL',\n CANCEL: 'CANCEL',\n };\n\n // Register the common set of modals.\n ModalRegistry.register(TYPES.DEFAULT, Modal, TEMPLATES.DEFAULT);\n ModalRegistry.register(TYPES.SAVE_CANCEL, ModalSaveCancel, TEMPLATES.SAVE_CANCEL);\n ModalRegistry.register(TYPES.CANCEL, ModalCancel, TEMPLATES.CANCEL);\n\n /**\n * Set up the events required to show the modal and return focus when the modal\n * is closed.\n *\n * @method setUpTrigger\n * @param {Promise} modalPromise The modal instance\n * @param {object} triggerElement The jQuery element to open the modal\n * @param {object} modalConfig The modal configuration given to the factory\n */\n var setUpTrigger = function(modalPromise, triggerElement, modalConfig) {\n // The element that actually shows the modal.\n var actualTriggerElement = null;\n // Check if the client has provided a callback function to be called\n // before the modal is displayed.\n var hasPreShowCallback = (typeof modalConfig.preShowCallback == 'function');\n // Function to handle the trigger element being activated.\n var triggeredCallback = function(e, data) {\n var pendingPromise = new Pending('core/modal_factory:setUpTrigger:triggeredCallback');\n actualTriggerElement = $(e.currentTarget);\n modalPromise.then(function(modal) {\n if (hasPreShowCallback) {\n // If the client provided a pre-show callback then execute\n // it now before showing the modal.\n modalConfig.preShowCallback(actualTriggerElement, modal);\n }\n\n modal.show();\n\n return modal;\n })\n .then(pendingPromise.resolve);\n data.originalEvent.preventDefault();\n };\n\n // The trigger element can either be a single element or it can be an\n // element + selector pair to create a delegated event handler to trigger\n // the modal.\n if (Array.isArray(triggerElement)) {\n var selector = triggerElement[1];\n triggerElement = triggerElement[0];\n\n CustomEvents.define(triggerElement, [CustomEvents.events.activate]);\n triggerElement.on(CustomEvents.events.activate, selector, triggeredCallback);\n } else {\n CustomEvents.define(triggerElement, [CustomEvents.events.activate]);\n triggerElement.on(CustomEvents.events.activate, triggeredCallback);\n }\n\n modalPromise.then(function(modal) {\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Focus on the trigger element that actually launched the modal.\n if (actualTriggerElement !== null) {\n actualTriggerElement.focus();\n }\n });\n\n return modal;\n });\n };\n\n /**\n * Create the correct instance of a modal based on the givem type. Sets up\n * the trigger between the modal and the trigger element.\n *\n * @method createFromElement\n * @param {object} registryConf A config from the ModalRegistry\n * @param {object} modalElement The modal HTML jQuery object\n * @return {object} Modal instance\n */\n var createFromElement = function(registryConf, modalElement) {\n modalElement = $(modalElement);\n var module = registryConf.module;\n var modal = new module(modalElement);\n\n return modal;\n };\n\n /**\n * Create the correct modal instance for the given type, including loading\n * the correct template.\n *\n * @method createFromType\n * @param {object} registryConf A config from the ModalRegistry\n * @param {object} templateContext The context to render the template with\n * @return {promise} Resolved with a Modal instance\n */\n var createFromType = function(registryConf, templateContext) {\n var templateName = registryConf.template;\n\n var modalPromise = Templates.render(templateName, templateContext)\n .then(function(html) {\n var modalElement = $(html);\n return createFromElement(registryConf, modalElement);\n })\n .fail(Notification.exception);\n\n return modalPromise;\n };\n\n /**\n * Create a Modal instance.\n *\n * @method create\n * @param {object} modalConfig The configuration to create the modal instance\n * @param {object} triggerElement The trigger HTML jQuery object\n * @return {promise} Resolved with a Modal instance\n */\n var create = function(modalConfig, triggerElement) {\n var type = modalConfig.type || TYPES.DEFAULT;\n var isLarge = modalConfig.large ? true : false;\n var registryConf = null;\n var templateContext = {};\n\n registryConf = ModalRegistry.get(type);\n\n if (!registryConf) {\n Notification.exception({message: 'Unable to find modal of type: ' + type});\n }\n\n if (typeof modalConfig.templateContext != 'undefined') {\n templateContext = modalConfig.templateContext;\n }\n\n var modalPromise = createFromType(registryConf, templateContext)\n .then(function(modal) {\n if (typeof modalConfig.title != 'undefined') {\n modal.setTitle(modalConfig.title);\n }\n\n if (typeof modalConfig.body != 'undefined') {\n modal.setBody(modalConfig.body);\n }\n\n if (typeof modalConfig.footer != 'undefined') {\n modal.setFooter(modalConfig.footer);\n }\n\n if (isLarge) {\n modal.setLarge();\n }\n\n return modal;\n });\n\n if (typeof triggerElement != 'undefined') {\n setUpTrigger(modalPromise, triggerElement, modalConfig);\n }\n\n return modalPromise;\n };\n\n return {\n create: create,\n types: TYPES,\n };\n});\n"],"file":"modal_factory.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/modal_factory.js"],"names":["define","$","ModalEvents","ModalRegistry","Modal","ModalSaveCancel","ModalCancel","ModalAlert","Templates","Notification","CustomEvents","Pending","TEMPLATES","DEFAULT","SAVE_CANCEL","CANCEL","ALERT","TYPES","register","setUpTrigger","modalPromise","triggerElement","modalConfig","actualTriggerElement","hasPreShowCallback","preShowCallback","triggeredCallback","e","data","pendingPromise","currentTarget","then","modal","show","resolve","originalEvent","preventDefault","Array","isArray","selector","events","activate","on","getRoot","hidden","focus","createFromElement","registryConf","modalElement","module","createFromType","templateContext","templateName","template","render","html","fail","exception","create","type","isLarge","large","get","message","title","setTitle","body","setBody","footer","setFooter","buttons","Object","entries","forEach","key","value","setButtonText","setLarge","removeOnClose","setRemoveOnClose","types"],"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 * Create a modal.\n *\n * @module core/modal_factory\n * @class modal_factory\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/modal_events', 'core/modal_registry', 'core/modal',\n 'core/modal_save_cancel', 'core/modal_cancel', 'core/local/modal/alert',\n 'core/templates', 'core/notification', 'core/custom_interaction_events',\n 'core/pending'],\n function($, ModalEvents, ModalRegistry, Modal, ModalSaveCancel,\n ModalCancel, ModalAlert, Templates, Notification, CustomEvents, Pending) {\n\n // The templates for each type of modal.\n var TEMPLATES = {\n DEFAULT: 'core/modal',\n SAVE_CANCEL: 'core/modal_save_cancel',\n CANCEL: 'core/modal_cancel',\n ALERT: 'core/local/modal/alert',\n };\n\n // The available types of modals.\n var TYPES = {\n DEFAULT: 'DEFAULT',\n SAVE_CANCEL: 'SAVE_CANCEL',\n CANCEL: 'CANCEL',\n ALERT: 'ALERT',\n };\n\n // Register the common set of modals.\n ModalRegistry.register(TYPES.DEFAULT, Modal, TEMPLATES.DEFAULT);\n ModalRegistry.register(TYPES.SAVE_CANCEL, ModalSaveCancel, TEMPLATES.SAVE_CANCEL);\n ModalRegistry.register(TYPES.CANCEL, ModalCancel, TEMPLATES.CANCEL);\n ModalRegistry.register(TYPES.ALERT, ModalAlert, TEMPLATES.ALERT);\n\n /**\n * Set up the events required to show the modal and return focus when the modal\n * is closed.\n *\n * @method setUpTrigger\n * @param {Promise} modalPromise The modal instance\n * @param {object} triggerElement The jQuery element to open the modal\n * @param {object} modalConfig The modal configuration given to the factory\n */\n var setUpTrigger = function(modalPromise, triggerElement, modalConfig) {\n // The element that actually shows the modal.\n var actualTriggerElement = null;\n // Check if the client has provided a callback function to be called\n // before the modal is displayed.\n var hasPreShowCallback = (typeof modalConfig.preShowCallback == 'function');\n // Function to handle the trigger element being activated.\n var triggeredCallback = function(e, data) {\n var pendingPromise = new Pending('core/modal_factory:setUpTrigger:triggeredCallback');\n actualTriggerElement = $(e.currentTarget);\n modalPromise.then(function(modal) {\n if (hasPreShowCallback) {\n // If the client provided a pre-show callback then execute\n // it now before showing the modal.\n modalConfig.preShowCallback(actualTriggerElement, modal);\n }\n\n modal.show();\n\n return modal;\n })\n .then(pendingPromise.resolve);\n data.originalEvent.preventDefault();\n };\n\n // The trigger element can either be a single element or it can be an\n // element + selector pair to create a delegated event handler to trigger\n // the modal.\n if (Array.isArray(triggerElement)) {\n var selector = triggerElement[1];\n triggerElement = triggerElement[0];\n\n CustomEvents.define(triggerElement, [CustomEvents.events.activate]);\n triggerElement.on(CustomEvents.events.activate, selector, triggeredCallback);\n } else {\n CustomEvents.define(triggerElement, [CustomEvents.events.activate]);\n triggerElement.on(CustomEvents.events.activate, triggeredCallback);\n }\n\n modalPromise.then(function(modal) {\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Focus on the trigger element that actually launched the modal.\n if (actualTriggerElement !== null) {\n actualTriggerElement.focus();\n }\n });\n\n return modal;\n });\n };\n\n /**\n * Create the correct instance of a modal based on the givem type. Sets up\n * the trigger between the modal and the trigger element.\n *\n * @method createFromElement\n * @param {object} registryConf A config from the ModalRegistry\n * @param {object} modalElement The modal HTML jQuery object\n * @return {object} Modal instance\n */\n var createFromElement = function(registryConf, modalElement) {\n modalElement = $(modalElement);\n var module = registryConf.module;\n var modal = new module(modalElement);\n\n return modal;\n };\n\n /**\n * Create the correct modal instance for the given type, including loading\n * the correct template.\n *\n * @method createFromType\n * @param {object} registryConf A config from the ModalRegistry\n * @param {object} templateContext The context to render the template with\n * @return {promise} Resolved with a Modal instance\n */\n var createFromType = function(registryConf, templateContext) {\n var templateName = registryConf.template;\n\n var modalPromise = Templates.render(templateName, templateContext)\n .then(function(html) {\n var modalElement = $(html);\n return createFromElement(registryConf, modalElement);\n })\n .fail(Notification.exception);\n\n return modalPromise;\n };\n\n /**\n * Create a Modal instance.\n *\n * @method create\n * @param {object} modalConfig The configuration to create the modal instance\n * @param {object} triggerElement The trigger HTML jQuery object\n * @return {promise} Resolved with a Modal instance\n */\n var create = function(modalConfig, triggerElement) {\n var type = modalConfig.type || TYPES.DEFAULT;\n var isLarge = modalConfig.large ? true : false;\n var registryConf = null;\n var templateContext = {};\n\n registryConf = ModalRegistry.get(type);\n\n if (!registryConf) {\n Notification.exception({message: 'Unable to find modal of type: ' + type});\n }\n\n if (typeof modalConfig.templateContext != 'undefined') {\n templateContext = modalConfig.templateContext;\n }\n\n var modalPromise = createFromType(registryConf, templateContext)\n .then(function(modal) {\n if (typeof modalConfig.title != 'undefined') {\n modal.setTitle(modalConfig.title);\n }\n\n if (typeof modalConfig.body != 'undefined') {\n modal.setBody(modalConfig.body);\n }\n\n if (typeof modalConfig.footer != 'undefined') {\n modal.setFooter(modalConfig.footer);\n }\n\n if (modalConfig.buttons) {\n Object.entries(modalConfig.buttons).forEach(function([key, value]) {\n modal.setButtonText(key, value);\n });\n }\n\n if (isLarge) {\n modal.setLarge();\n }\n\n if (typeof modalConfig.removeOnClose !== 'undefined') {\n // If configured remove the modal when hiding it.\n modal.setRemoveOnClose(modalConfig.removeOnClose);\n }\n\n return modal;\n });\n\n if (typeof triggerElement != 'undefined') {\n setUpTrigger(modalPromise, triggerElement, modalConfig);\n }\n\n return modalPromise;\n };\n\n return {\n create: create,\n types: TYPES,\n };\n});\n"],"file":"modal_factory.min.js"} \ No newline at end of file diff --git a/lib/amd/build/modal_save_cancel.min.js b/lib/amd/build/modal_save_cancel.min.js index 2a02302e517..5cf92def507 100644 --- a/lib/amd/build/modal_save_cancel.min.js +++ b/lib/amd/build/modal_save_cancel.min.js @@ -1,2 +1,2 @@ -define ("core/modal_save_cancel",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events"],function(a,b,c,d,f){var g={SAVE_BUTTON:"[data-action=\"save\"]",CANCEL_BUTTON:"[data-action=\"cancel\"]"},h=function(a){d.call(this,a);if(!this.getFooter().find(g.SAVE_BUTTON).length){b.exception({message:"No save button found"})}if(!this.getFooter().find(g.CANCEL_BUTTON).length){b.exception({message:"No cancel button found"})}};h.prototype=Object.create(d.prototype);h.prototype.constructor=h;h.prototype.setFooter=function(){b.exception({message:"Can not change the footer of a save cancel modal"})};h.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this);this.getModal().on(c.events.activate,g.SAVE_BUTTON,function(b,c){var d=a.Event(f.save);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,g.CANCEL_BUTTON,function(b,c){var d=a.Event(f.cancel);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this))};h.prototype.setSaveButtonText=function(a){var b=this.getFooter().find(g.SAVE_BUTTON);this.asyncSet(a,b.text.bind(b))};return h}); +define ("core/modal_save_cancel",["exports","core/modal"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function c(a){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;c.\n\n/**\n * Contain the logic for the save/cancel modal.\n *\n * @module core/modal_save_cancel\n * @class modal_save_cancel\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/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_events'],\n function($, Notification, CustomEvents, Modal, ModalEvents) {\n\n var SELECTORS = {\n SAVE_BUTTON: '[data-action=\"save\"]',\n CANCEL_BUTTON: '[data-action=\"cancel\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalSaveCancel = function(root) {\n Modal.call(this, root);\n\n if (!this.getFooter().find(SELECTORS.SAVE_BUTTON).length) {\n Notification.exception({message: 'No save button found'});\n }\n\n if (!this.getFooter().find(SELECTORS.CANCEL_BUTTON).length) {\n Notification.exception({message: 'No cancel button found'});\n }\n };\n\n ModalSaveCancel.prototype = Object.create(Modal.prototype);\n ModalSaveCancel.prototype.constructor = ModalSaveCancel;\n\n /**\n * Override parent implementation to prevent changing the footer content.\n */\n ModalSaveCancel.prototype.setFooter = function() {\n Notification.exception({message: 'Can not change the footer of a save cancel modal'});\n return;\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalSaveCancel.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, function(e, data) {\n var saveEvent = $.Event(ModalEvents.save);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) {\n var cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n /**\n * Allows to overwrite the text of \"Save changes\" 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 {(String|object)} value The button text, or a jQuery promise which will resolve it\n */\n ModalSaveCancel.prototype.setSaveButtonText = function(value) {\n var button = this.getFooter().find(SELECTORS.SAVE_BUTTON);\n\n this.asyncSet(value, button.text.bind(button));\n };\n\n return ModalSaveCancel;\n});\n"],"file":"modal_save_cancel.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/modal_save_cancel.js"],"names":["root","getFooter","find","getActionSelector","length","Notification","exception","message","registerCloseOnSave","registerCloseOnCancel","value","setButtonText","Modal"],"mappings":"uJAwBA,uD,gjDAGI,WAAYA,CAAZ,CAAkB,iBACd,wBAAMA,CAAN,GAEA,GAAI,CAAC,EAAKC,SAAL,GAAiBC,IAAjB,CAAsB,EAAKC,iBAAL,CAAuB,MAAvB,CAAtB,EAAsDC,MAA3D,CAAmE,CAC/DC,YAAY,CAACC,SAAb,CAAuB,CAACC,OAAO,CAAE,sBAAV,CAAvB,CACH,CAED,GAAI,CAAC,EAAKN,SAAL,GAAiBC,IAAjB,CAAsB,EAAKC,iBAAL,CAAuB,QAAvB,CAAtB,EAAwDC,MAA7D,CAAqE,CACjEC,YAAY,CAACC,SAAb,CAAuB,CAACC,OAAO,CAAE,wBAAV,CAAvB,CACH,CATa,QAUjB,C,0EAKwB,CAErB,2DAGA,KAAKC,mBAAL,GACA,KAAKC,qBAAL,EACH,C,6CAKW,CACRJ,YAAY,CAACC,SAAb,CAAuB,CAACC,OAAO,CAAE,kDAAV,CAAvB,CAEH,C,4DAQiBG,C,CAAO,CACrB,MAAO,MAAKC,aAAL,CAAmB,MAAnB,CAA2BD,CAA3B,CACV,C,cAzCwBE,S","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 the save/cancel modal.\n *\n * @module core/modal_save_cancel\n * @class modal_save_cancel\n * @package core\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Modal from 'core/modal';\n\nexport default class extends Modal {\n constructor(root) {\n super(root);\n\n if (!this.getFooter().find(this.getActionSelector('save')).length) {\n Notification.exception({message: 'No save button found'});\n }\n\n if (!this.getFooter().find(this.getActionSelector('cancel')).length) {\n Notification.exception({message: 'No cancel button found'});\n }\n }\n\n /**\n * Register all event listeners.\n */\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on save/cancel.\n this.registerCloseOnSave();\n this.registerCloseOnCancel();\n }\n\n /**\n * Override parent implementation to prevent changing the footer content.\n */\n setFooter() {\n Notification.exception({message: 'Can not change the footer of a save cancel modal'});\n return;\n }\n\n /**\n * Set the title of the save button.\n *\n * @param {String|Promise} value The button text, or a Promise which will resolve it\n * @returns{Promise}\n */\n setSaveButtonText(value) {\n return this.setButtonText('save', value);\n }\n}\n"],"file":"modal_save_cancel.min.js"} \ No newline at end of file diff --git a/lib/amd/build/notification.min.js b/lib/amd/build/notification.min.js index 4e559a2f810..e2a0bd32faa 100644 --- a/lib/amd/build/notification.min.js +++ b/lib/amd/build/notification.min.js @@ -1,2 +1,2 @@ -define ("core/notification",["core/yui","jquery","core/log","core/pending"],function(a,b,c,d){var e={types:{success:"core/notification_success",info:"core/notification_info",warning:"core/notification_warning",error:"core/notification_error"},fieldName:"user-notifications",fetchNotifications:function fetchNotifications(){var a=new d("core/notification:fetchNotifications");require(["core/ajax"],function(b){var c=b.call([{methodname:"core_fetch_notifications",args:{contextid:e.contextid}}]);c[0].then(e.addNotifications).always(a.resolve)})},addNotifications:function addNotifications(a){var c=new d("core/notification:addNotifications");if(!a){a=[]}b.each(a,function(a,b){e.renderNotification(b.template,b.variables)});c.resolve()},setupTargetRegion:function setupTargetRegion(){var a=b("#"+e.fieldName);if(a.length){return!1}var c=b("").attr("id",e.fieldName);a=b("#region-main");if(a.length){return a.prepend(c)}a=b("[role=\"main\"]");if(a.length){return a.prepend(c)}a=b("body");return a.prepend(c)},addNotification:function addNotification(a){var c=new d("core/notification:addNotifications"),f=e.types.error;a=b.extend({closebutton:!0,announce:!0,type:"error"},a);if(a.template){f=a.template;delete a.template}else if(a.type){if("undefined"!=typeof e.types[a.type]){f=e.types[a.type]}delete a.type}c.resolve();return e.renderNotification(f,a)},renderNotification:function renderNotification(a,f){if("undefined"==typeof f.message||!f.message){c.debug("Notification received without content. Skipping.");return}var g=new d("core/notification:renderNotification");require(["core/templates"],function(c){c.render(a,f).then(function(a,d){b("#"+e.fieldName).prepend(a);c.runTemplateJS(d)}).always(g.resolve).catch(e.exception)})},alert:function alert(b,c,e){var f=new d("core/notification:alert");a.use("moodle-core-notification-alert",function(){var a=new M.core.alert({title:b,message:c,yesLabel:e});a.show();f.resolve()})},confirm:function confirm(b,c,e,f,g,h){var i=new d("core/notification:confirm");a.use("moodle-core-notification-confirm",function(){var a=new M.core.confirm({title:b,question:c,yesLabel:e,noLabel:f});a.on("complete-yes",function(){g()});if(h){a.on("complete-no",function(){h()})}a.show();i.resolve()})},exception:function exception(b){var c=new d("core/notification:addNotifications");if("undefined"==typeof b.stack){b.stack=""}if(b.debuginfo){b.stack+=b.debuginfo+"\n"}if(!b.backtrace&&b.stacktrace){b.backtrace=b.stacktrace}if(b.backtrace){b.stack+=b.backtrace;var e=b.backtrace.match(/line ([^ ]*) of/),f=b.backtrace.match(/ of ([^:]*): /);if(e&&e[1]){b.lineNumber=e[1]}if(f&&f[1]){b.fileName=f[1];if(30.\n\n/**\n * A system for displaying notifications to users from the session.\n *\n * Wrapper for the YUI M.core.notification class. Allows us to\n * use the YUI version in AMD code until it is replaced.\n *\n * @module core/notification\n * @class notification\n * @package core\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 2.9\n */\ndefine(['core/yui', 'jquery', 'core/log', 'core/pending'],\nfunction(Y, $, log, Pending) {\n var notificationModule = {\n types: {\n 'success': 'core/notification_success',\n 'info': 'core/notification_info',\n 'warning': 'core/notification_warning',\n 'error': 'core/notification_error',\n },\n\n fieldName: 'user-notifications',\n\n fetchNotifications: function() {\n var pendingPromise = new Pending('core/notification:fetchNotifications');\n\n require(['core/ajax'], function(ajax) {\n var promises = ajax.call([{\n methodname: 'core_fetch_notifications',\n args: {\n contextid: notificationModule.contextid\n }\n }]);\n\n // This currently fails when not logged in.\n // eslint-disable-next-line promise/catch-or-return\n promises[0]\n .then(notificationModule.addNotifications)\n .always(pendingPromise.resolve);\n });\n },\n\n addNotifications: function(notifications) {\n var pendingPromise = new Pending('core/notification:addNotifications');\n\n if (!notifications) {\n notifications = [];\n }\n\n $.each(notifications, function(i, notification) {\n notificationModule.renderNotification(notification.template, notification.variables);\n });\n\n pendingPromise.resolve();\n },\n\n setupTargetRegion: function() {\n var targetRegion = $('#' + notificationModule.fieldName);\n if (targetRegion.length) {\n return false;\n }\n\n var newRegion = $('').attr('id', notificationModule.fieldName);\n\n targetRegion = $('#region-main');\n if (targetRegion.length) {\n return targetRegion.prepend(newRegion);\n }\n\n targetRegion = $('[role=\"main\"]');\n if (targetRegion.length) {\n return targetRegion.prepend(newRegion);\n }\n\n targetRegion = $('body');\n return targetRegion.prepend(newRegion);\n },\n\n addNotification: function(notification) {\n var pendingPromise = new Pending('core/notification:addNotifications');\n\n var template = notificationModule.types.error;\n\n notification = $.extend({\n closebutton: true,\n announce: true,\n type: 'error'\n }, notification);\n\n if (notification.template) {\n template = notification.template;\n delete notification.template;\n } else if (notification.type) {\n if (typeof notificationModule.types[notification.type] !== 'undefined') {\n template = notificationModule.types[notification.type];\n }\n delete notification.type;\n }\n\n pendingPromise.resolve();\n\n return notificationModule.renderNotification(template, notification);\n },\n\n renderNotification: function(template, variables) {\n if (typeof variables.message === 'undefined' || !variables.message) {\n log.debug('Notification received without content. Skipping.');\n return;\n }\n\n var pendingPromise = new Pending('core/notification:renderNotification');\n\n require(['core/templates'], function(templates) {\n templates.render(template, variables)\n .then(function(html, js) {\n $('#' + notificationModule.fieldName).prepend(html);\n templates.runTemplateJS(js);\n\n return;\n })\n .always(pendingPromise.resolve)\n .catch(notificationModule.exception);\n });\n },\n\n alert: function(title, message, yesLabel) {\n var pendingPromise = new Pending('core/notification:alert');\n\n // Here we are wrapping YUI. This allows us to start transitioning, but\n // wait for a good alternative without having inconsistent dialogues.\n Y.use('moodle-core-notification-alert', function() {\n var alert = new M.core.alert({\n title: title,\n message: message,\n yesLabel: yesLabel\n });\n\n alert.show();\n\n pendingPromise.resolve();\n });\n },\n\n confirm: function(title, question, yesLabel, noLabel, yesCallback, noCallback) {\n var pendingPromise = new Pending('core/notification:confirm');\n\n // Here we are wrapping YUI. This allows us to start transitioning, but\n // wait for a good alternative without having inconsistent dialogues.\n Y.use('moodle-core-notification-confirm', function() {\n var modal = new M.core.confirm({\n title: title,\n question: question,\n yesLabel: yesLabel,\n noLabel: noLabel\n });\n\n modal.on('complete-yes', function() {\n yesCallback();\n });\n if (noCallback) {\n modal.on('complete-no', function() {\n noCallback();\n });\n }\n modal.show();\n\n pendingPromise.resolve();\n });\n },\n\n exception: function(ex) {\n var pendingPromise = new Pending('core/notification:addNotifications');\n\n // Fudge some parameters.\n if (typeof ex.stack == 'undefined') {\n ex.stack = '';\n }\n if (ex.debuginfo) {\n ex.stack += ex.debuginfo + '\\n';\n }\n if (!ex.backtrace && ex.stacktrace) {\n ex.backtrace = ex.stacktrace;\n }\n if (ex.backtrace) {\n ex.stack += ex.backtrace;\n var ln = ex.backtrace.match(/line ([^ ]*) of/);\n var fn = ex.backtrace.match(/ of ([^:]*): /);\n if (ln && ln[1]) {\n ex.lineNumber = ln[1];\n }\n if (fn && fn[1]) {\n ex.fileName = fn[1];\n if (ex.fileName.length > 30) {\n ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 27);\n }\n }\n }\n if (typeof ex.name == 'undefined' && ex.errorcode) {\n ex.name = ex.errorcode;\n }\n\n Y.use('moodle-core-notification-exception', function() {\n var modal = new M.core.exception(ex);\n\n modal.show();\n\n pendingPromise.resolve();\n });\n }\n };\n\n return /** @alias module:core/notification */{\n init: function(contextid, notifications) {\n notificationModule.contextid = contextid;\n\n // Setup the message target region if it isn't setup already\n notificationModule.setupTargetRegion();\n\n // Add provided notifications.\n notificationModule.addNotifications(notifications);\n\n // Poll for any new notifications.\n notificationModule.fetchNotifications();\n },\n\n /**\n * Poll the server for any new notifications.\n *\n * @method fetchNotifications\n */\n fetchNotifications: notificationModule.fetchNotifications,\n\n /**\n * Add a notification to the page.\n *\n * Note: This does not cause the notification to be added to the session.\n *\n * @method addNotification\n * @param {Object} notification The notification to add.\n * @param {string} notification.message The body of the notification\n * @param {string} notification.type The type of notification to add (error, warning, info, success).\n * @param {Boolean} notification.closebutton Whether to show the close button.\n * @param {Boolean} notification.announce Whether to announce to screen readers.\n */\n addNotification: notificationModule.addNotification,\n\n /**\n * Wrap M.core.alert.\n *\n * @method alert\n * @param {string} title\n * @param {string} message\n * @param {string} yesLabel\n */\n alert: notificationModule.alert,\n\n /**\n * Wrap M.core.confirm.\n *\n * @method confirm\n * @param {string} title\n * @param {string} question\n * @param {string} yesLabel\n * @param {string} noLabel\n * @param {function} yesCallback\n * @param {function} noCallback Optional parameter to be called if the user presses cancel.\n */\n confirm: notificationModule.confirm,\n\n /**\n * Wrap M.core.exception.\n *\n * @method exception\n * @param {Error} ex\n */\n exception: notificationModule.exception\n };\n});\n"],"file":"notification.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/notification.js"],"names":["currentContextId","M","cfg","contextid","notificationTypes","success","info","warning","error","notificationRegionId","Selectors","notificationRegion","fallbackRegionParents","setupTargetRegion","targetRegion","getNotificationRegion","newRegion","document","createElement","id","some","selector","querySelector","prepend","fetchNotifications","Ajax","call","methodname","args","then","addNotifications","notifications","length","Promise","resolve","pendingPromise","Pending","forEach","notification","renderNotification","template","variables","addNotification","closebutton","announce","type","message","Log","debug","Templates","renderForPromise","html","js","prependNodeContents","catch","exception","alert","title","cancelText","ModalFactory","create","types","ALERT","body","buttons","cancel","removeOnClose","modal","show","confirm","question","saveLabel","noLabel","saveCallback","cancelCallback","saveCancel","all","ModalEvents","SAVE_CANCEL","save","getRoot","on","ex","stack","debuginfo","backtrace","stacktrace","ln","match","fn","lineNumber","fileName","substr","name","errorcode","Y","use","core","init","contextId","notificationList"],"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\nimport Pending from 'core/pending';\nimport Log from 'core/log';\n\nlet currentContextId = M.cfg.contextid;\n\nconst notificationTypes = {\n success: 'core/notification_success',\n info: 'core/notification_info',\n warning: 'core/notification_warning',\n error: 'core/notification_error',\n};\n\nconst notificationRegionId = 'user-notifications';\n\nconst Selectors = {\n notificationRegion: `#${notificationRegionId}`,\n fallbackRegionParents: [\n '#region-main',\n '[role=\"main\"]',\n 'body',\n ],\n};\n\nconst setupTargetRegion = () => {\n let targetRegion = getNotificationRegion();\n if (targetRegion) {\n return false;\n }\n\n const newRegion = document.createElement('span');\n newRegion.id = notificationRegionId;\n\n return Selectors.fallbackRegionParents.some(selector => {\n const targetRegion = document.querySelector(selector);\n\n if (targetRegion) {\n targetRegion.prepend(newRegion);\n return true;\n }\n\n return false;\n });\n};\n\n\n/**\n * Poll the server for any new notifications.\n *\n * @returns {Promise}\n */\nexport const fetchNotifications = async() => {\n const Ajax = await import('core/ajax');\n\n return Ajax.call([{\n methodname: 'core_fetch_notifications',\n args: {\n contextid: currentContextId\n }\n }])[0]\n .then(addNotifications);\n};\n\n/**\n * Add all of the supplied notifications.\n *\n * @param {Array} notifications The list of notificaitons\n * @returns {Promise}\n */\nconst addNotifications = notifications => {\n if (!notifications.length) {\n return Promise.resolve();\n }\n\n const pendingPromise = new Pending('core/notification:addNotifications');\n notifications.forEach(notification => renderNotification(notification.template, notification.variables));\n\n return pendingPromise.resolve();\n};\n\n/**\n * Add a notification to the page.\n *\n * Note: This does not cause the notification to be added to the session.\n *\n * @param {Object} notification The notification to add.\n * @param {string} notification.message The body of the notification\n * @param {string} notification.type The type of notification to add (error, warning, info, success).\n * @param {Boolean} notification.closebutton Whether to show the close button.\n * @param {Boolean} notification.announce Whether to announce to screen readers.\n * @returns {Promise}\n */\nexport const addNotification = notification => {\n const pendingPromise = new Pending('core/notification:addNotifications');\n\n let template = notificationTypes.error;\n\n notification = {\n closebutton: true,\n announce: true,\n type: 'error',\n ...notification,\n };\n\n if (notification.template) {\n template = notification.template;\n delete notification.template;\n } else if (notification.type) {\n if (typeof notificationTypes[notification.type] !== 'undefined') {\n template = notificationTypes[notification.type];\n }\n delete notification.type;\n }\n\n return renderNotification(template, notification)\n .then(pendingPromise.resolve);\n};\n\nconst renderNotification = async(template, variables) => {\n if (typeof variables.message === 'undefined' || !variables.message) {\n Log.debug('Notification received without content. Skipping.');\n return;\n }\n\n const pendingPromise = new Pending('core/notification:renderNotification');\n const Templates = await import('core/templates');\n\n Templates.renderForPromise(template, variables)\n .then(({html, js = ''}) => {\n Templates.prependNodeContents(getNotificationRegion(), html, js);\n\n return;\n })\n .then(pendingPromise.resolve)\n .catch(exception);\n};\n\nconst getNotificationRegion = () => document.querySelector(Selectors.notificationRegion);\n\n/**\n * Alert dialogue.\n *\n * @param {String|Promise} title\n * @param {String|Promise} message\n * @param {String|Promise} cancelText\n * @returns {Promise}\n */\nexport const alert = async(title, message, cancelText) => {\n var pendingPromise = new Pending('core/notification:alert');\n\n const ModalFactory = await import('core/modal_factory');\n\n return ModalFactory.create({\n type: ModalFactory.types.ALERT,\n body: message,\n title: title,\n buttons: {\n cancel: cancelText,\n },\n removeOnClose: true,\n })\n .then(function(modal) {\n modal.show();\n\n pendingPromise.resolve();\n return modal;\n });\n};\n\n/**\n * The confirm has now been replaced with a save and cancel dialogue.\n *\n * @param {String|Promise} title\n * @param {String|Promise} question\n * @param {String|Promise} saveLabel\n * @param {String|Promise} noLabel\n * @param {String|Promise} saveCallback\n * @param {String|Promise} cancelCallback\n * @returns {Promise}\n */\nexport const confirm = (title, question, saveLabel, noLabel, saveCallback, cancelCallback) =>\n saveCancel(title, question, saveLabel, saveCallback, cancelCallback);\n\n/**\n * The Save and Cancel dialogue helper.\n *\n * @param {String|Promise} title\n * @param {String|Promise} question\n * @param {String|Promise} saveLabel\n * @param {String|Promise} saveCallback\n * @param {String|Promise} cancelCallback\n * @returns {Promise}\n */\nexport const saveCancel = async(title, question, saveLabel, saveCallback, cancelCallback) => {\n const pendingPromise = new Pending('core/notification:confirm');\n\n const [\n ModalFactory,\n ModalEvents,\n ] = await Promise.all([\n import('core/modal_factory'),\n import('core/modal_events'),\n ]);\n\n return ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: question,\n buttons: {\n // Note: The noLabel is no longer supported.\n save: saveLabel,\n },\n removeOnClose: true,\n })\n .then(function(modal) {\n modal.show();\n\n modal.getRoot().on(ModalEvents.save, saveCallback);\n modal.getRoot().on(ModalEvents.cancel, cancelCallback);\n pendingPromise.resolve();\n\n return modal;\n });\n};\n\n/**\n * Wrap M.core.exception.\n *\n * @param {Error} ex\n */\nexport const exception = async ex => {\n const pendingPromise = new Pending('core/notification:displayException');\n\n // Fudge some parameters.\n if (!ex.stack) {\n ex.stack = '';\n }\n\n if (ex.debuginfo) {\n ex.stack += ex.debuginfo + '\\n';\n }\n\n if (!ex.backtrace && ex.stacktrace) {\n ex.backtrace = ex.stacktrace;\n }\n\n if (ex.backtrace) {\n ex.stack += ex.backtrace;\n const ln = ex.backtrace.match(/line ([^ ]*) of/);\n const fn = ex.backtrace.match(/ of ([^:]*): /);\n if (ln && ln[1]) {\n ex.lineNumber = ln[1];\n }\n if (fn && fn[1]) {\n ex.fileName = fn[1];\n if (ex.fileName.length > 30) {\n ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 27);\n }\n }\n }\n\n if (typeof ex.name === 'undefined' && ex.errorcode) {\n ex.name = ex.errorcode;\n }\n\n const Y = await import('core/yui');\n Y.use('moodle-core-notification-exception', function() {\n var modal = new M.core.exception(ex);\n\n modal.show();\n\n pendingPromise.resolve();\n });\n};\n\n/**\n * Initialise the page for the suppled context, and displaying the supplied notifications.\n *\n * @param {Number} contextId\n * @param {Array} notificationList\n */\nexport const init = (contextId, notificationList) => {\n currentContextId = contextId;\n\n // Setup the message target region if it isn't setup already\n setupTargetRegion();\n\n // Add provided notifications.\n addNotifications(notificationList);\n\n // Perform an initial poll for any new notifications.\n fetchNotifications();\n};\n\n// To maintain backwards compatability we export default here.\nexport default {\n init,\n fetchNotifications,\n addNotification,\n alert,\n confirm,\n saveCancel,\n exception,\n};\n"],"file":"notification.min.js"} \ No newline at end of file diff --git a/lib/amd/src/local/modal/alert.js b/lib/amd/src/local/modal/alert.js new file mode 100644 index 00000000000..da90eef974f --- /dev/null +++ b/lib/amd/src/local/modal/alert.js @@ -0,0 +1,39 @@ +// 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 . + +/** + * Alert modal. + * + * @module core/modal_alert + * @class modal_alert + * @package core + * @copyright 2020 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Modal from 'core/modal'; + +export default class extends Modal { + /** + * Register all event listeners. + */ + registerEventListeners() { + // Call the parent registration. + super.registerEventListeners(); + + // Register to close on cancel. + this.registerCloseOnCancel(); + } +} diff --git a/lib/amd/src/modal.js b/lib/amd/src/modal.js index aeefaedf888..154f9746fef 100644 --- a/lib/amd/src/modal.js +++ b/lib/amd/src/modal.js @@ -610,10 +610,11 @@ define([ * already been. * * @method show + * @returns {Promise} */ Modal.prototype.show = function() { if (this.isVisible()) { - return; + return $.Deferred().resolve(); } var pendingPromise = new Pending('core/modal:show'); @@ -628,7 +629,7 @@ define([ this.attachToDOM(); } - this.getBackdrop() + return this.getBackdrop() .then(function(backdrop) { var currentIndex = this.calculateZIndex(); var newIndex = currentIndex + 2; @@ -699,6 +700,7 @@ define([ * @method destroy */ Modal.prototype.destroy = function() { + this.hide(); this.root.remove(); this.root.trigger(ModalEvents.destroyed, this); }; @@ -802,6 +804,52 @@ define([ }.bind(this)); }; + /** + * Register a listener to close the dialogue when the cancel button is pressed. + * + * @method registerCloseOnCancel + */ + Modal.prototype.registerCloseOnCancel = function() { + // Handle the clicking of the Cancel button. + this.getModal().on(CustomEvents.events.activate, this.getActionSelector('cancel'), function(e, data) { + var cancelEvent = $.Event(ModalEvents.cancel); + this.getRoot().trigger(cancelEvent, this); + + if (!cancelEvent.isDefaultPrevented()) { + data.originalEvent.preventDefault(); + + if (this.removeOnClose) { + this.destroy(); + } else { + this.hide(); + } + } + }.bind(this)); + }; + + /** + * Register a listener to close the dialogue when the save button is pressed. + * + * @method registerCloseOnSave + */ + Modal.prototype.registerCloseOnSave = function() { + // Handle the clicking of the Cancel button. + this.getModal().on(CustomEvents.events.activate, this.getActionSelector('save'), function(e, data) { + var saveEvent = $.Event(ModalEvents.save); + this.getRoot().trigger(saveEvent, this); + + if (!saveEvent.isDefaultPrevented()) { + data.originalEvent.preventDefault(); + + if (this.removeOnClose) { + this.destroy(); + } else { + this.hide(); + } + } + }.bind(this)); + }; + /** * Set or resolve and set the value using the function. * @@ -827,5 +875,44 @@ define([ return p; }; + /** + * Set the title text of a button. + * + * This method is overloaded to take either a string value for the button title or a jQuery promise that is resolved with + * text most commonly from a Str.get_string call. + * + * @param {DOMString} action The action of the button + * @param {(String|object)} value The button text, or a promise which will resolve to it + * @returns {Promise} + */ + Modal.prototype.setButtonText = function(action, value) { + const button = this.getFooter().find(this.getActionSelector(action)); + + if (!button) { + throw new Error("Unable to find the '" + action + "' button"); + } + + return this.asyncSet(value, button.text.bind(button)); + }; + + /** + * Get the Selector for an action. + * + * @param {String} action + * @returns {DOMString} + */ + Modal.prototype.getActionSelector = function(action) { + return "[data-action='" + action + "']"; + }; + + /** + * Set the flag to remove the modal from the DOM on close. + * + * @param {Boolean} remove + */ + Modal.prototype.setRemoveOnClose = function(remove) { + this.removeOnClose = remove; + }; + return Modal; }); diff --git a/lib/amd/src/modal_cancel.js b/lib/amd/src/modal_cancel.js index 2e182c1e2d2..8f593f0c8fa 100644 --- a/lib/amd/src/modal_cancel.js +++ b/lib/amd/src/modal_cancel.js @@ -22,56 +22,25 @@ * @copyright 2016 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_events'], - function($, Notification, CustomEvents, Modal, ModalEvents) { +import Modal from 'core/modal'; - var SELECTORS = { - CANCEL_BUTTON: '[data-action="cancel"]', - }; +export default class extends Modal { + constructor(root) { + super(root); - /** - * Constructor for the Modal. - * - * @param {object} root The root jQuery element for the modal - */ - var ModalCancel = function(root) { - Modal.call(this, root); - - if (!this.getFooter().find(SELECTORS.CANCEL_BUTTON).length) { + if (!this.getFooter().find(this.getActionSelector('cancel')).length) { Notification.exception({message: 'No cancel button found'}); } - }; - - ModalCancel.prototype = Object.create(Modal.prototype); - ModalCancel.prototype.constructor = ModalCancel; + } /** - * Override parent implementation to prevent changing the footer content. + * Register all event listeners. */ - ModalCancel.prototype.setFooter = function() { - Notification.exception({message: 'Can not change the footer of a cancel modal'}); - return; - }; + registerEventListeners() { + // Call the parent registration. + super.registerEventListeners(); - /** - * Set up all of the event handling for the modal. - * - * @method registerEventListeners - */ - ModalCancel.prototype.registerEventListeners = function() { - // Apply parent event listeners. - Modal.prototype.registerEventListeners.call(this); - - this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) { - var cancelEvent = $.Event(ModalEvents.cancel); - this.getRoot().trigger(cancelEvent, this); - - if (!cancelEvent.isDefaultPrevented()) { - this.hide(); - data.originalEvent.preventDefault(); - } - }.bind(this)); - }; - - return ModalCancel; -}); + // Register to close on cancel. + this.registerCloseOnCancel(); + } +} diff --git a/lib/amd/src/modal_factory.js b/lib/amd/src/modal_factory.js index 2b304bc6428..1e27c2f1d89 100644 --- a/lib/amd/src/modal_factory.js +++ b/lib/amd/src/modal_factory.js @@ -23,17 +23,18 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define(['jquery', 'core/modal_events', 'core/modal_registry', 'core/modal', - 'core/modal_save_cancel', 'core/modal_cancel', + 'core/modal_save_cancel', 'core/modal_cancel', 'core/local/modal/alert', 'core/templates', 'core/notification', 'core/custom_interaction_events', 'core/pending'], function($, ModalEvents, ModalRegistry, Modal, ModalSaveCancel, - ModalCancel, Templates, Notification, CustomEvents, Pending) { + ModalCancel, ModalAlert, Templates, Notification, CustomEvents, Pending) { // The templates for each type of modal. var TEMPLATES = { DEFAULT: 'core/modal', SAVE_CANCEL: 'core/modal_save_cancel', CANCEL: 'core/modal_cancel', + ALERT: 'core/local/modal/alert', }; // The available types of modals. @@ -41,12 +42,14 @@ define(['jquery', 'core/modal_events', 'core/modal_registry', 'core/modal', DEFAULT: 'DEFAULT', SAVE_CANCEL: 'SAVE_CANCEL', CANCEL: 'CANCEL', + ALERT: 'ALERT', }; // Register the common set of modals. ModalRegistry.register(TYPES.DEFAULT, Modal, TEMPLATES.DEFAULT); ModalRegistry.register(TYPES.SAVE_CANCEL, ModalSaveCancel, TEMPLATES.SAVE_CANCEL); ModalRegistry.register(TYPES.CANCEL, ModalCancel, TEMPLATES.CANCEL); + ModalRegistry.register(TYPES.ALERT, ModalAlert, TEMPLATES.ALERT); /** * Set up the events required to show the modal and return focus when the modal @@ -185,10 +188,21 @@ define(['jquery', 'core/modal_events', 'core/modal_registry', 'core/modal', modal.setFooter(modalConfig.footer); } + if (modalConfig.buttons) { + Object.entries(modalConfig.buttons).forEach(function([key, value]) { + modal.setButtonText(key, value); + }); + } + if (isLarge) { modal.setLarge(); } + if (typeof modalConfig.removeOnClose !== 'undefined') { + // If configured remove the modal when hiding it. + modal.setRemoveOnClose(modalConfig.removeOnClose); + } + return modal; }); diff --git a/lib/amd/src/modal_save_cancel.js b/lib/amd/src/modal_save_cancel.js index f62751c48db..42416bebfcd 100644 --- a/lib/amd/src/modal_save_cancel.js +++ b/lib/amd/src/modal_save_cancel.js @@ -22,85 +22,48 @@ * @copyright 2016 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_events'], - function($, Notification, CustomEvents, Modal, ModalEvents) { +import Modal from 'core/modal'; - var SELECTORS = { - SAVE_BUTTON: '[data-action="save"]', - CANCEL_BUTTON: '[data-action="cancel"]', - }; +export default class extends Modal { + constructor(root) { + super(root); - /** - * Constructor for the Modal. - * - * @param {object} root The root jQuery element for the modal - */ - var ModalSaveCancel = function(root) { - Modal.call(this, root); - - if (!this.getFooter().find(SELECTORS.SAVE_BUTTON).length) { + if (!this.getFooter().find(this.getActionSelector('save')).length) { Notification.exception({message: 'No save button found'}); } - if (!this.getFooter().find(SELECTORS.CANCEL_BUTTON).length) { + if (!this.getFooter().find(this.getActionSelector('cancel')).length) { Notification.exception({message: 'No cancel button found'}); } - }; + } - ModalSaveCancel.prototype = Object.create(Modal.prototype); - ModalSaveCancel.prototype.constructor = ModalSaveCancel; + /** + * Register all event listeners. + */ + registerEventListeners() { + // Call the parent registration. + super.registerEventListeners(); + + // Register to close on save/cancel. + this.registerCloseOnSave(); + this.registerCloseOnCancel(); + } /** * Override parent implementation to prevent changing the footer content. */ - ModalSaveCancel.prototype.setFooter = function() { + setFooter() { Notification.exception({message: 'Can not change the footer of a save cancel modal'}); return; - }; + } /** - * Set up all of the event handling for the modal. + * Set the title of the save button. * - * @method registerEventListeners + * @param {String|Promise} value The button text, or a Promise which will resolve it + * @returns{Promise} */ - ModalSaveCancel.prototype.registerEventListeners = function() { - // Apply parent event listeners. - Modal.prototype.registerEventListeners.call(this); - - this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, function(e, data) { - var saveEvent = $.Event(ModalEvents.save); - this.getRoot().trigger(saveEvent, this); - - if (!saveEvent.isDefaultPrevented()) { - this.hide(); - data.originalEvent.preventDefault(); - } - }.bind(this)); - - this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) { - var cancelEvent = $.Event(ModalEvents.cancel); - this.getRoot().trigger(cancelEvent, this); - - if (!cancelEvent.isDefaultPrevented()) { - this.hide(); - data.originalEvent.preventDefault(); - } - }.bind(this)); - }; - - /** - * Allows to overwrite the text of "Save changes" button. - * - * This method is overloaded to take either a string value for the button title or a jQuery promise that is resolved with - * text most commonly from a Str.get_string call. - * - * @param {(String|object)} value The button text, or a jQuery promise which will resolve it - */ - ModalSaveCancel.prototype.setSaveButtonText = function(value) { - var button = this.getFooter().find(SELECTORS.SAVE_BUTTON); - - this.asyncSet(value, button.text.bind(button)); - }; - - return ModalSaveCancel; -}); + setSaveButtonText(value) { + return this.setButtonText('save', value); + } +} diff --git a/lib/amd/src/notification.js b/lib/amd/src/notification.js index 3bbe59f3094..08228999171 100644 --- a/lib/amd/src/notification.js +++ b/lib/amd/src/notification.js @@ -13,283 +13,306 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * A system for displaying notifications to users from the session. - * - * Wrapper for the YUI M.core.notification class. Allows us to - * use the YUI version in AMD code until it is replaced. - * - * @module core/notification - * @class notification - * @package core - * @copyright 2015 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since 2.9 - */ -define(['core/yui', 'jquery', 'core/log', 'core/pending'], -function(Y, $, log, Pending) { - var notificationModule = { - types: { - 'success': 'core/notification_success', - 'info': 'core/notification_info', - 'warning': 'core/notification_warning', - 'error': 'core/notification_error', - }, +import Pending from 'core/pending'; +import Log from 'core/log'; - fieldName: 'user-notifications', +let currentContextId = M.cfg.contextid; - fetchNotifications: function() { - var pendingPromise = new Pending('core/notification:fetchNotifications'); +const notificationTypes = { + success: 'core/notification_success', + info: 'core/notification_info', + warning: 'core/notification_warning', + error: 'core/notification_error', +}; - require(['core/ajax'], function(ajax) { - var promises = ajax.call([{ - methodname: 'core_fetch_notifications', - args: { - contextid: notificationModule.contextid - } - }]); +const notificationRegionId = 'user-notifications'; - // This currently fails when not logged in. - // eslint-disable-next-line promise/catch-or-return - promises[0] - .then(notificationModule.addNotifications) - .always(pendingPromise.resolve); - }); - }, +const Selectors = { + notificationRegion: `#${notificationRegionId}`, + fallbackRegionParents: [ + '#region-main', + '[role="main"]', + 'body', + ], +}; - addNotifications: function(notifications) { - var pendingPromise = new Pending('core/notification:addNotifications'); +const setupTargetRegion = () => { + let targetRegion = getNotificationRegion(); + if (targetRegion) { + return false; + } - if (!notifications) { - notifications = []; - } + const newRegion = document.createElement('span'); + newRegion.id = notificationRegionId; - $.each(notifications, function(i, notification) { - notificationModule.renderNotification(notification.template, notification.variables); - }); + return Selectors.fallbackRegionParents.some(selector => { + const targetRegion = document.querySelector(selector); - pendingPromise.resolve(); - }, - - setupTargetRegion: function() { - var targetRegion = $('#' + notificationModule.fieldName); - if (targetRegion.length) { - return false; - } - - var newRegion = $('').attr('id', notificationModule.fieldName); - - targetRegion = $('#region-main'); - if (targetRegion.length) { - return targetRegion.prepend(newRegion); - } - - targetRegion = $('[role="main"]'); - if (targetRegion.length) { - return targetRegion.prepend(newRegion); - } - - targetRegion = $('body'); - return targetRegion.prepend(newRegion); - }, - - addNotification: function(notification) { - var pendingPromise = new Pending('core/notification:addNotifications'); - - var template = notificationModule.types.error; - - notification = $.extend({ - closebutton: true, - announce: true, - type: 'error' - }, notification); - - if (notification.template) { - template = notification.template; - delete notification.template; - } else if (notification.type) { - if (typeof notificationModule.types[notification.type] !== 'undefined') { - template = notificationModule.types[notification.type]; - } - delete notification.type; - } - - pendingPromise.resolve(); - - return notificationModule.renderNotification(template, notification); - }, - - renderNotification: function(template, variables) { - if (typeof variables.message === 'undefined' || !variables.message) { - log.debug('Notification received without content. Skipping.'); - return; - } - - var pendingPromise = new Pending('core/notification:renderNotification'); - - require(['core/templates'], function(templates) { - templates.render(template, variables) - .then(function(html, js) { - $('#' + notificationModule.fieldName).prepend(html); - templates.runTemplateJS(js); - - return; - }) - .always(pendingPromise.resolve) - .catch(notificationModule.exception); - }); - }, - - alert: function(title, message, yesLabel) { - var pendingPromise = new Pending('core/notification:alert'); - - // Here we are wrapping YUI. This allows us to start transitioning, but - // wait for a good alternative without having inconsistent dialogues. - Y.use('moodle-core-notification-alert', function() { - var alert = new M.core.alert({ - title: title, - message: message, - yesLabel: yesLabel - }); - - alert.show(); - - pendingPromise.resolve(); - }); - }, - - confirm: function(title, question, yesLabel, noLabel, yesCallback, noCallback) { - var pendingPromise = new Pending('core/notification:confirm'); - - // Here we are wrapping YUI. This allows us to start transitioning, but - // wait for a good alternative without having inconsistent dialogues. - Y.use('moodle-core-notification-confirm', function() { - var modal = new M.core.confirm({ - title: title, - question: question, - yesLabel: yesLabel, - noLabel: noLabel - }); - - modal.on('complete-yes', function() { - yesCallback(); - }); - if (noCallback) { - modal.on('complete-no', function() { - noCallback(); - }); - } - modal.show(); - - pendingPromise.resolve(); - }); - }, - - exception: function(ex) { - var pendingPromise = new Pending('core/notification:addNotifications'); - - // Fudge some parameters. - if (typeof ex.stack == 'undefined') { - ex.stack = ''; - } - if (ex.debuginfo) { - ex.stack += ex.debuginfo + '\n'; - } - if (!ex.backtrace && ex.stacktrace) { - ex.backtrace = ex.stacktrace; - } - if (ex.backtrace) { - ex.stack += ex.backtrace; - var ln = ex.backtrace.match(/line ([^ ]*) of/); - var fn = ex.backtrace.match(/ of ([^:]*): /); - if (ln && ln[1]) { - ex.lineNumber = ln[1]; - } - if (fn && fn[1]) { - ex.fileName = fn[1]; - if (ex.fileName.length > 30) { - ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 27); - } - } - } - if (typeof ex.name == 'undefined' && ex.errorcode) { - ex.name = ex.errorcode; - } - - Y.use('moodle-core-notification-exception', function() { - var modal = new M.core.exception(ex); - - modal.show(); - - pendingPromise.resolve(); - }); + if (targetRegion) { + targetRegion.prepend(newRegion); + return true; } + + return false; + }); +}; + + +/** + * Poll the server for any new notifications. + * + * @returns {Promise} + */ +export const fetchNotifications = async() => { + const Ajax = await import('core/ajax'); + + return Ajax.call([{ + methodname: 'core_fetch_notifications', + args: { + contextid: currentContextId + } + }])[0] + .then(addNotifications); +}; + +/** + * Add all of the supplied notifications. + * + * @param {Array} notifications The list of notificaitons + * @returns {Promise} + */ +const addNotifications = notifications => { + if (!notifications.length) { + return Promise.resolve(); + } + + const pendingPromise = new Pending('core/notification:addNotifications'); + notifications.forEach(notification => renderNotification(notification.template, notification.variables)); + + return pendingPromise.resolve(); +}; + +/** + * Add a notification to the page. + * + * Note: This does not cause the notification to be added to the session. + * + * @param {Object} notification The notification to add. + * @param {string} notification.message The body of the notification + * @param {string} notification.type The type of notification to add (error, warning, info, success). + * @param {Boolean} notification.closebutton Whether to show the close button. + * @param {Boolean} notification.announce Whether to announce to screen readers. + * @returns {Promise} + */ +export const addNotification = notification => { + const pendingPromise = new Pending('core/notification:addNotifications'); + + let template = notificationTypes.error; + + notification = { + closebutton: true, + announce: true, + type: 'error', + ...notification, }; - return /** @alias module:core/notification */{ - init: function(contextid, notifications) { - notificationModule.contextid = contextid; + if (notification.template) { + template = notification.template; + delete notification.template; + } else if (notification.type) { + if (typeof notificationTypes[notification.type] !== 'undefined') { + template = notificationTypes[notification.type]; + } + delete notification.type; + } - // Setup the message target region if it isn't setup already - notificationModule.setupTargetRegion(); + return renderNotification(template, notification) + .then(pendingPromise.resolve); +}; - // Add provided notifications. - notificationModule.addNotifications(notifications); +const renderNotification = async(template, variables) => { + if (typeof variables.message === 'undefined' || !variables.message) { + Log.debug('Notification received without content. Skipping.'); + return; + } - // Poll for any new notifications. - notificationModule.fetchNotifications(); + const pendingPromise = new Pending('core/notification:renderNotification'); + const Templates = await import('core/templates'); + + Templates.renderForPromise(template, variables) + .then(({html, js = ''}) => { + Templates.prependNodeContents(getNotificationRegion(), html, js); + + return; + }) + .then(pendingPromise.resolve) + .catch(exception); +}; + +const getNotificationRegion = () => document.querySelector(Selectors.notificationRegion); + +/** + * Alert dialogue. + * + * @param {String|Promise} title + * @param {String|Promise} message + * @param {String|Promise} cancelText + * @returns {Promise} + */ +export const alert = async(title, message, cancelText) => { + var pendingPromise = new Pending('core/notification:alert'); + + const ModalFactory = await import('core/modal_factory'); + + return ModalFactory.create({ + type: ModalFactory.types.ALERT, + body: message, + title: title, + buttons: { + cancel: cancelText, }, + removeOnClose: true, + }) + .then(function(modal) { + modal.show(); - /** - * Poll the server for any new notifications. - * - * @method fetchNotifications - */ - fetchNotifications: notificationModule.fetchNotifications, + pendingPromise.resolve(); + return modal; + }); +}; - /** - * Add a notification to the page. - * - * Note: This does not cause the notification to be added to the session. - * - * @method addNotification - * @param {Object} notification The notification to add. - * @param {string} notification.message The body of the notification - * @param {string} notification.type The type of notification to add (error, warning, info, success). - * @param {Boolean} notification.closebutton Whether to show the close button. - * @param {Boolean} notification.announce Whether to announce to screen readers. - */ - addNotification: notificationModule.addNotification, +/** + * The confirm has now been replaced with a save and cancel dialogue. + * + * @param {String|Promise} title + * @param {String|Promise} question + * @param {String|Promise} saveLabel + * @param {String|Promise} noLabel + * @param {String|Promise} saveCallback + * @param {String|Promise} cancelCallback + * @returns {Promise} + */ +export const confirm = (title, question, saveLabel, noLabel, saveCallback, cancelCallback) => + saveCancel(title, question, saveLabel, saveCallback, cancelCallback); - /** - * Wrap M.core.alert. - * - * @method alert - * @param {string} title - * @param {string} message - * @param {string} yesLabel - */ - alert: notificationModule.alert, +/** + * The Save and Cancel dialogue helper. + * + * @param {String|Promise} title + * @param {String|Promise} question + * @param {String|Promise} saveLabel + * @param {String|Promise} saveCallback + * @param {String|Promise} cancelCallback + * @returns {Promise} + */ +export const saveCancel = async(title, question, saveLabel, saveCallback, cancelCallback) => { + const pendingPromise = new Pending('core/notification:confirm'); - /** - * Wrap M.core.confirm. - * - * @method confirm - * @param {string} title - * @param {string} question - * @param {string} yesLabel - * @param {string} noLabel - * @param {function} yesCallback - * @param {function} noCallback Optional parameter to be called if the user presses cancel. - */ - confirm: notificationModule.confirm, + const [ + ModalFactory, + ModalEvents, + ] = await Promise.all([ + import('core/modal_factory'), + import('core/modal_events'), + ]); - /** - * Wrap M.core.exception. - * - * @method exception - * @param {Error} ex - */ - exception: notificationModule.exception - }; -}); + return ModalFactory.create({ + type: ModalFactory.types.SAVE_CANCEL, + title: title, + body: question, + buttons: { + // Note: The noLabel is no longer supported. + save: saveLabel, + }, + removeOnClose: true, + }) + .then(function(modal) { + modal.show(); + + modal.getRoot().on(ModalEvents.save, saveCallback); + modal.getRoot().on(ModalEvents.cancel, cancelCallback); + pendingPromise.resolve(); + + return modal; + }); +}; + +/** + * Wrap M.core.exception. + * + * @param {Error} ex + */ +export const exception = async ex => { + const pendingPromise = new Pending('core/notification:displayException'); + + // Fudge some parameters. + if (!ex.stack) { + ex.stack = ''; + } + + if (ex.debuginfo) { + ex.stack += ex.debuginfo + '\n'; + } + + if (!ex.backtrace && ex.stacktrace) { + ex.backtrace = ex.stacktrace; + } + + if (ex.backtrace) { + ex.stack += ex.backtrace; + const ln = ex.backtrace.match(/line ([^ ]*) of/); + const fn = ex.backtrace.match(/ of ([^:]*): /); + if (ln && ln[1]) { + ex.lineNumber = ln[1]; + } + if (fn && fn[1]) { + ex.fileName = fn[1]; + if (ex.fileName.length > 30) { + ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 27); + } + } + } + + if (typeof ex.name === 'undefined' && ex.errorcode) { + ex.name = ex.errorcode; + } + + const Y = await import('core/yui'); + Y.use('moodle-core-notification-exception', function() { + var modal = new M.core.exception(ex); + + modal.show(); + + pendingPromise.resolve(); + }); +}; + +/** + * Initialise the page for the suppled context, and displaying the supplied notifications. + * + * @param {Number} contextId + * @param {Array} notificationList + */ +export const init = (contextId, notificationList) => { + currentContextId = contextId; + + // Setup the message target region if it isn't setup already + setupTargetRegion(); + + // Add provided notifications. + addNotifications(notificationList); + + // Perform an initial poll for any new notifications. + fetchNotifications(); +}; + +// To maintain backwards compatability we export default here. +export default { + init, + fetchNotifications, + addNotification, + alert, + confirm, + saveCancel, + exception, +}; diff --git a/lib/templates/local/modal/alert.mustache b/lib/templates/local/modal/alert.mustache new file mode 100644 index 00000000000..78ce7cd79cb --- /dev/null +++ b/lib/templates/local/modal/alert.mustache @@ -0,0 +1,45 @@ +{{! + 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 . +}} +{{! + @template core/local/modal/alert + + Moodle modal template with one oaky button. + + The purpose of this template is to render an alert modal with an acceptance option. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * title A cleaned string (use clean_text()) to display. + * body HTML content for the boday + + Example context (json): + { + "title": "Example cancel modal", + "body": "Some example content for the body" + } +}} + +{{< core/modal }} + {{$footer}} + + {{/footer}} +{{/ core/modal }} diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 04d9108bae6..8fa66f4118b 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -49,6 +49,9 @@ information provided here is intended especially for developers. * Implement a more direct xsendfile_file() method for an alternative_file_system_class * A new `dynamic` table interface has been defined, which allows any `flexible_table` to be converted into a table which is updatable via ajax calls. See MDL-68495 and `\core_table\dynamic` for further information. +* The core/notification module has been updated to use AMD modals for its confirmation and alert dialogues. + The confirmation dialogue no longer has a configurable "No" button as per similar changes in MDL-59759. + This set of confirmation modals was unintentionally missed from that deprecation process. === 3.8 === * Add CLI option to notify all cron tasks to stop: admin/cli/cron.php --stop diff --git a/mod/assign/feedback/editpdf/tests/behat/view_previous_annotations.feature b/mod/assign/feedback/editpdf/tests/behat/view_previous_annotations.feature index b593498dd7f..1b341ee1781 100644 --- a/mod/assign/feedback/editpdf/tests/behat/view_previous_annotations.feature +++ b/mod/assign/feedback/editpdf/tests/behat/view_previous_annotations.feature @@ -56,7 +56,7 @@ Feature: In an assignment, teacher can view the feedback for a previous attempt. And I should see "The changes to the grade and feedback were saved" And I press "Ok" And I follow "View a different attempt" - And I click on "//div[contains(@class, 'moodle-dialogue-bd')]//label[2]" "xpath_element" + And I click on "Attempt 1" "radio" in the "View a different attempt" "dialogue" And I press "View" And I wait until the page is ready And I should see "You are editing the feedback for a previous attempt. This is attempt 1 out of 2." diff --git a/mod/assign/tests/behat/edit_previous_feedback.feature b/mod/assign/tests/behat/edit_previous_feedback.feature index 007d4fda396..add1bec001b 100644 --- a/mod/assign/tests/behat/edit_previous_feedback.feature +++ b/mod/assign/tests/behat/edit_previous_feedback.feature @@ -60,7 +60,7 @@ Feature: In an assignment, teachers can edit feedback for a students previous su And I navigate to "View all submissions" in current page administration And I click on "Grade" "link" in the "Student 2" "table_row" And I click on "View a different attempt" "link" - And I click on "//div[contains(concat(' ', normalize-space(@class), ' '), ' confirmation-dialogue ')]//input[@value='0']" "xpath_element" + And I click on "Attempt 1" "radio" in the "View a different attempt" "dialogue" And I click on "View" "button" And I set the following fields to these values: | Grade | 50 | diff --git a/tag/tests/behat/delete_tag.feature b/tag/tests/behat/delete_tag.feature index 542360426d2..18eb048f16a 100644 --- a/tag/tests/behat/delete_tag.feature +++ b/tag/tests/behat/delete_tag.feature @@ -53,7 +53,7 @@ Feature: Manager is able to delete tags And I follow "Default collection" And I click on "Delete" "link" in the "Turtle" "table_row" Then I should see "Are you sure you want to delete this tag?" - And I press "No" + And I click on "Cancel" "button" in the "Delete" "dialogue" And I should not see "Tag(s) deleted" And I should see "Turtle" And I click on "Delete" "link" in the "Dog" "table_row" @@ -81,7 +81,7 @@ Feature: Manager is able to delete tags | Select tag Cat | 1 | And I press "Delete selected" And I should see "Are you sure you want to delete selected tags?" - And I press "No" + And I click on "Cancel" "button" in the "Delete" "dialogue" And I should not see "Tag(s) deleted" And I should see "Cat" And I set the following fields to these values: