");return t.setStyle("margin",e.margin),i.getStyle("margin")===t.getStyle("margin")&&(i.addClass(this._getAlignmentClass(e.value)),i.setStyle(e.name,null),i.setStyle("margin",null),!0)},this),i},_getAlignmentClass:function(e){return u.ALIGNSETTINGS+"_"+e},_updateWarning:function(){var e=this._form,t=!0,i=e.one("."+u.INPUTALT).get("value"),n=e.one("."+u.IMAGEPRESENTATION).get("checked");return t=""!==i||n?(e.one("."+u.IMAGEALTWARNING).setStyle("display","none"),e.one("."+u.INPUTALT).setAttribute("aria-invalid",!1),e.one("."+u.IMAGEPRESENTATION).setAttribute("aria-invalid",!1),!1):(e.one("."+u.IMAGEALTWARNING).setStyle("display","block"),e.one("."+u.INPUTALT).setAttribute("aria-invalid",!0),e.one("."+u.IMAGEPRESENTATION).setAttribute("aria-invalid",!0),!0),this.getDialogue().centerDialogue(),t},_handleKeyup:function(){var e=this._form,t=e.one("."+u.INPUTALT).get("value").length;e.one("#currentcount").setHTML(t)}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]});
\ No newline at end of file
diff --git a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
index 707fb72e6bc..7d7bd769cb2 100644
--- a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
+++ b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
@@ -358,6 +358,11 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
host.saveSelection();
+ // Trigger form upload start events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadStarted(self.editor.get('id'));
+ });
+
var options = host.get('filepickeroptions').image,
savepath = (options.savepath === undefined) ? '/' : options.savepath,
formData = new FormData(),
@@ -412,6 +417,10 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
if (placeholder) {
placeholder.remove(true);
}
+ // Trigger form upload complete events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadCompleted(self.editor.get('id'));
+ });
throw new M.core.ajaxException(result);
}
@@ -439,12 +448,20 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
} else {
Y.use('moodle-core-notification-alert', function() {
+ // Trigger form upload complete events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadCompleted(self.editor.get('id'));
+ });
new M.core.alert({message: M.util.get_string('servererror', 'moodle')});
});
if (placeholder) {
placeholder.remove(true);
}
}
+ // Trigger form upload complete events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadCompleted(self.editor.get('id'));
+ });
}
};
xhr.open("POST", M.cfg.wwwroot + '/repository/repository_ajax.php?action=upload', true);
diff --git a/lib/editor/atto/plugins/image/yui/src/button/js/button.js b/lib/editor/atto/plugins/image/yui/src/button/js/button.js
index 0c6c6af633a..9acf253851d 100644
--- a/lib/editor/atto/plugins/image/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/image/yui/src/button/js/button.js
@@ -356,6 +356,11 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
host.saveSelection();
+ // Trigger form upload start events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadStarted(self.editor.get('id'));
+ });
+
var options = host.get('filepickeroptions').image,
savepath = (options.savepath === undefined) ? '/' : options.savepath,
formData = new FormData(),
@@ -410,6 +415,10 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
if (placeholder) {
placeholder.remove(true);
}
+ // Trigger form upload complete events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadCompleted(self.editor.get('id'));
+ });
throw new M.core.ajaxException(result);
}
@@ -437,12 +446,20 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
} else {
Y.use('moodle-core-notification-alert', function() {
+ // Trigger form upload complete events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadCompleted(self.editor.get('id'));
+ });
new M.core.alert({message: M.util.get_string('servererror', 'moodle')});
});
if (placeholder) {
placeholder.remove(true);
}
}
+ // Trigger form upload complete events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadCompleted(self.editor.get('id'));
+ });
}
};
xhr.open("POST", M.cfg.wwwroot + '/repository/repository_ajax.php?action=upload', true);
diff --git a/lib/form/amd/build/events.min.js b/lib/form/amd/build/events.min.js
new file mode 100644
index 00000000000..80ab166769f
--- /dev/null
+++ b/lib/form/amd/build/events.min.js
@@ -0,0 +1,2 @@
+define ("core_form/events",["exports","core/str"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.triggerUploadCompleted=a.triggerUploadStarted=a.types=void 0;var c;(0,b.get_string)("changesmadereallygoaway","moodle").then(function(a){c=a;return a}).catch();var d=function(a){if(a){a.returnValue=c}},e={uploadStarted:"core_form/uploadStarted",uploadCompleted:"core_form/uploadCompleted"};a.types=e;a.triggerUploadStarted=function triggerUploadStarted(a){window.addEventListener("beforeunload",d);var b=new CustomEvent(e.uploadStarted,{bubbles:!0,cancellable:!1}),c=document.getElementById(a);c.dispatchEvent(b);return b};a.triggerUploadCompleted=function triggerUploadCompleted(a){window.removeEventListener("beforeunload",d);var b=new CustomEvent(e.uploadCompleted,{bubbles:!0,cancellable:!1}),c=document.getElementById(a);c.dispatchEvent(b);return b}});
+//# sourceMappingURL=events.min.js.map
diff --git a/lib/form/amd/build/events.min.js.map b/lib/form/amd/build/events.min.js.map
new file mode 100644
index 00000000000..a890d5a138c
--- /dev/null
+++ b/lib/form/amd/build/events.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/events.js"],"names":["changesMadeString","then","string","catch","changesMadeCheck","e","returnValue","types","uploadStarted","uploadCompleted","triggerUploadStarted","elementId","window","addEventListener","customEvent","CustomEvent","bubbles","cancellable","element","document","getElementById","dispatchEvent","triggerUploadCompleted","removeEventListener"],"mappings":"6LA2BA,GAAIA,CAAAA,CAAJ,CACA,iBAAU,yBAAV,CAAqC,QAArC,EAA+CC,IAA/C,CAAoD,SAAAC,CAAM,CAAI,CAC1DF,CAAiB,CAAGE,CAApB,CACA,MAAOA,CAAAA,CACV,CAHD,EAGGC,KAHH,G,GASMC,CAAAA,CAAgB,CAAG,SAAAC,CAAC,CAAI,CAC1B,GAAIA,CAAJ,CAAO,CACHA,CAAC,CAACC,WAAF,CAAgBN,CACnB,CACJ,C,CAKYO,CAAK,CAAG,CACjBC,aAAa,CAAE,yBADE,CAEjBC,eAAe,CAAE,2BAFA,C,kCAWe,QAAvBC,CAAAA,oBAAuB,CAAAC,CAAS,CAAI,CAE7CC,MAAM,CAACC,gBAAP,CAAwB,cAAxB,CAAwCT,CAAxC,EAF6C,GAGvCU,CAAAA,CAAW,CAAG,GAAIC,CAAAA,WAAJ,CAAgBR,CAAK,CAACC,aAAtB,CAAqC,CACrDQ,OAAO,GAD8C,CAErDC,WAAW,GAF0C,CAArC,CAHyB,CAOvCC,CAAO,CAAGC,QAAQ,CAACC,cAAT,CAAwBT,CAAxB,CAP6B,CAQ7CO,CAAO,CAACG,aAAR,CAAsBP,CAAtB,EAEA,MAAOA,CAAAA,CACV,C,0BAQqC,QAAzBQ,CAAAA,sBAAyB,CAAAX,CAAS,CAAI,CAE/CC,MAAM,CAACW,mBAAP,CAA2B,cAA3B,CAA2CnB,CAA3C,EAF+C,GAGzCU,CAAAA,CAAW,CAAG,GAAIC,CAAAA,WAAJ,CAAgBR,CAAK,CAACE,eAAtB,CAAuC,CACvDO,OAAO,GADgD,CAEvDC,WAAW,GAF4C,CAAvC,CAH2B,CAOzCC,CAAO,CAAGC,QAAQ,CAACC,cAAT,CAAwBT,CAAxB,CAP+B,CAQ/CO,CAAO,CAACG,aAAR,CAAsBP,CAAtB,EAEA,MAAOA,CAAAA,CACV,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Contain the events the form component can trigger.\n *\n * @module core_form/events\n * @package core_form\n * @copyright 2021 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.10\n */\n\nimport {get_string as getString} from 'core/str';\n\nlet changesMadeString;\ngetString('changesmadereallygoaway', 'moodle').then(string => {\n changesMadeString = string;\n return string;\n}).catch();\n\n/**\n * Prevent user navigate away when upload progress still running.\n * @param {Event} e The event\n */\nconst changesMadeCheck = e => {\n if (e) {\n e.returnValue = changesMadeString;\n }\n};\n\n/**\n * List of the events.\n **/\nexport const types = {\n uploadStarted: 'core_form/uploadStarted',\n uploadCompleted: 'core_form/uploadCompleted',\n};\n\n/**\n * Trigger upload start event.\n *\n * @param {String} elementId\n * @returns {CustomEvent}\n */\nexport const triggerUploadStarted = elementId => {\n // Add an additional check for changes made.\n window.addEventListener('beforeunload', changesMadeCheck);\n const customEvent = new CustomEvent(types.uploadStarted, {\n bubbles: true,\n cancellable: false\n });\n const element = document.getElementById(elementId);\n element.dispatchEvent(customEvent);\n\n return customEvent;\n};\n\n/**\n * Trigger upload complete event.\n *\n * @param {String} elementId\n * @returns {CustomEvent}\n */\nexport const triggerUploadCompleted = elementId => {\n // Remove the additional check for changes made.\n window.removeEventListener('beforeunload', changesMadeCheck);\n const customEvent = new CustomEvent(types.uploadCompleted, {\n bubbles: true,\n cancellable: false\n });\n const element = document.getElementById(elementId);\n element.dispatchEvent(customEvent);\n\n return customEvent;\n};\n"],"file":"events.min.js"}
\ No newline at end of file
diff --git a/lib/form/amd/build/submit.min.js b/lib/form/amd/build/submit.min.js
index 2631f659ebe..cfce3d6380c 100644
--- a/lib/form/amd/build/submit.min.js
+++ b/lib/form/amd/build/submit.min.js
@@ -1,2 +1,2 @@
-define ("core_form/submit",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var b=0,c=[],d=function(a){c.push(a);if(!b){b=setInterval(function(){var a=document.cookie.split(e()+"=");if(2==a.length){f();clearInterval(b);b=0;c.forEach(function(a){a.disabled=!1})}},500)}},e=function(){return"moodledownload_"+M.cfg.sesskey},f=function(){document.cookie=encodeURIComponent(e())+"=deleted; expires="+new Date(0).toUTCString()};a.init=function init(a){var b=document.getElementById(a);if("off"===b.form.dataset.doubleSubmitProtection){return}b.form.addEventListener("submit",function(a){var c=function(){if(a.defaultPrevented||b.disabled){return}b.disabled=!0;f();d(b)};window.addEventListener("beforeunload",c);setTimeout(function(){window.removeEventListener("beforeunload",c)},0)},!1)}});
+define ("core_form/submit",["exports","core_form/events"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var c=0,d=[],e=function(a){d.push(a);if(!c){c=setInterval(function(){var a=document.cookie.split(f()+"=");if(2==a.length){g();clearInterval(c);c=0;d.forEach(function(a){a.disabled=!1})}},500)}},f=function(){return"moodledownload_"+M.cfg.sesskey},g=function(){document.cookie=encodeURIComponent(f())+"=deleted; expires="+new Date(0).toUTCString()};a.init=function init(a){var c=document.getElementById(a);document.addEventListener(b.types.uploadStarted,function(a){window.console.log(a.target);c.disabled=!0});document.addEventListener(b.types.uploadCompleted,function(a){window.console.log(a.target);c.disabled=!1});if("off"===c.form.dataset.doubleSubmitProtection){return}c.form.addEventListener("submit",function(a){var b=function(){if(a.defaultPrevented||c.disabled){return}c.disabled=!0;g();e(c)};window.addEventListener("beforeunload",b);setTimeout(function(){window.removeEventListener("beforeunload",b)},0)},!1)}});
//# sourceMappingURL=submit.min.js.map
diff --git a/lib/form/amd/build/submit.min.js.map b/lib/form/amd/build/submit.min.js.map
index 164962313cf..a488d4cb8c8 100644
--- a/lib/form/amd/build/submit.min.js.map
+++ b/lib/form/amd/build/submit.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/submit.js"],"names":["cookieListener","cookieListeningButtons","listenForDownloadCookie","button","push","setInterval","parts","document","cookie","split","getCookieName","length","clearDownloadCookie","clearInterval","forEach","disabled","M","cfg","sesskey","encodeURIComponent","Date","toUTCString","init","elementId","getElementById","form","dataset","doubleSubmitProtection","addEventListener","event","disableAction","defaultPrevented","window","setTimeout","removeEventListener"],"mappings":"kIA2BIA,CAAAA,CAAc,CAAG,C,CAGfC,CAAsB,CAAG,E,CAazBC,CAAuB,CAAG,SAACC,CAAD,CAAY,CACxCF,CAAsB,CAACG,IAAvB,CAA4BD,CAA5B,EACA,GAAI,CAACH,CAAL,CAAqB,CACjBA,CAAc,CAAGK,WAAW,CAAC,UAAM,CAE/B,GAAMC,CAAAA,CAAK,CAAGC,QAAQ,CAACC,MAAT,CAAgBC,KAAhB,CAAsBC,CAAa,GAAK,GAAxC,CAAd,CACA,GAAoB,CAAhB,EAAAJ,CAAK,CAACK,MAAV,CAAuB,CAEnBC,CAAmB,GACnBC,aAAa,CAACb,CAAD,CAAb,CACAA,CAAc,CAAG,CAAjB,CAGAC,CAAsB,CAACa,OAAvB,CAA+B,SAACX,CAAD,CAAY,CACvCA,CAAM,CAACY,QAAP,GACH,CAFD,CAGH,CACJ,CAd2B,CAczB,GAdyB,CAe/B,CACJ,C,CAOKL,CAAa,CAAG,UAAM,CACxB,MAAO,kBAAoBM,CAAC,CAACC,GAAF,CAAMC,OACpC,C,CAKKN,CAAmB,CAAG,UAAM,CAC9BL,QAAQ,CAACC,MAAT,CAAkBW,kBAAkB,CAACT,CAAa,EAAd,CAAlB,CAAsC,oBAAtC,CAA6D,GAAIU,CAAAA,IAAJ,CAAS,CAAT,EAAYC,WAAZ,EAClF,C,QAOmB,QAAPC,CAAAA,IAAO,CAACC,CAAD,CAAe,CAC/B,GAAMpB,CAAAA,CAAM,CAAGI,QAAQ,CAACiB,cAAT,CAAwBD,CAAxB,CAAf,CAEA,GAAmD,KAA/C,GAAApB,CAAM,CAACsB,IAAP,CAAYC,OAAZ,CAAoBC,sBAAxB,CAA0D,CACtD,MACH,CACDxB,CAAM,CAACsB,IAAP,CAAYG,gBAAZ,CAA6B,QAA7B,CAAuC,SAASC,CAAT,CAAgB,CAGnD,GAAMC,CAAAA,CAAa,CAAG,UAAW,CAE7B,GAAID,CAAK,CAACE,gBAAN,EAA0B5B,CAAM,CAACY,QAArC,CAA+C,CAC3C,MACH,CAEDZ,CAAM,CAACY,QAAP,IACAH,CAAmB,GACnBV,CAAuB,CAACC,CAAD,CAC1B,CATD,CAUA6B,MAAM,CAACJ,gBAAP,CAAwB,cAAxB,CAAwCE,CAAxC,EAIAG,UAAU,CAAC,UAAW,CAClBD,MAAM,CAACE,mBAAP,CAA2B,cAA3B,CAA2CJ,CAA3C,CACH,CAFS,CAEP,CAFO,CAGb,CApBD,IAqBH,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Submit button JavaScript. All submit buttons will be automatically disabled once the form is\n * submitted, unless that submission results in an error/cancelling the submit.\n *\n * @module core_form/submit\n * @package core_form\n * @copyright 2019 The Open University\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.8\n */\n\n/** @type {number} ID for setInterval used when polling for download cookie */\nlet cookieListener = 0;\n\n/** @type {Array} Array of buttons that need re-enabling if we get a download cookie */\nconst cookieListeningButtons = [];\n\n/**\n * Listens in case a download cookie is provided.\n *\n * This function is used to detect file downloads. If there is a file download then we get a\n * beforeunload event, but the page is never unloaded and when the file download completes we\n * should re-enable the buttons. We detect this by watching for a specific cookie.\n *\n * PHP function \\core_form\\util::form_download_complete() can be used to send this cookie.\n *\n * @param {HTMLElement} button Button to re-enable\n */\nconst listenForDownloadCookie = (button) => {\n cookieListeningButtons.push(button);\n if (!cookieListener) {\n cookieListener = setInterval(() => {\n // Look for cookie.\n const parts = document.cookie.split(getCookieName() + '=');\n if (parts.length == 2) {\n // We found the cookie, so the file is ready. Expire the cookie and cancel polling.\n clearDownloadCookie();\n clearInterval(cookieListener);\n cookieListener = 0;\n\n // Re-enable all the buttons.\n cookieListeningButtons.forEach((button) => {\n button.disabled = false;\n });\n }\n }, 500);\n }\n};\n\n/**\n * Gets a unique name for the download cookie.\n *\n * @returns {string} Cookie name\n */\nconst getCookieName = () => {\n return 'moodledownload_' + M.cfg.sesskey;\n};\n\n/**\n * Clears the download cookie if there is one.\n */\nconst clearDownloadCookie = () => {\n document.cookie = encodeURIComponent(getCookieName()) + '=deleted; expires=' + new Date(0).toUTCString();\n};\n\n/**\n * Initialises submit buttons.\n *\n * @param {String} elementId Form element\n */\nexport const init = (elementId) => {\n const button = document.getElementById(elementId);\n // If the form has double submit protection disabled, do nothing.\n if (button.form.dataset.doubleSubmitProtection === 'off') {\n return;\n }\n button.form.addEventListener('submit', function(event) {\n // Only disable it if the browser is really going to another page as a result of the\n // submit.\n const disableAction = function() {\n // If the submit was cancelled, or the button is already disabled, don't do anything.\n if (event.defaultPrevented || button.disabled) {\n return;\n }\n\n button.disabled = true;\n clearDownloadCookie();\n listenForDownloadCookie(button);\n };\n window.addEventListener('beforeunload', disableAction);\n // If there is no beforeunload event as a result of this form submit, then the form\n // submit must have been cancelled, so don't disable the button if the page is\n // unloaded later.\n setTimeout(function() {\n window.removeEventListener('beforeunload', disableAction);\n }, 0);\n }, false);\n};\n"],"file":"submit.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/submit.js"],"names":["cookieListener","cookieListeningButtons","listenForDownloadCookie","button","push","setInterval","parts","document","cookie","split","getCookieName","length","clearDownloadCookie","clearInterval","forEach","disabled","M","cfg","sesskey","encodeURIComponent","Date","toUTCString","init","elementId","getElementById","addEventListener","types","uploadStarted","e","window","console","log","target","uploadCompleted","form","dataset","doubleSubmitProtection","event","disableAction","defaultPrevented","setTimeout","removeEventListener"],"mappings":"uJA6BIA,CAAAA,CAAc,CAAG,C,CAGfC,CAAsB,CAAG,E,CAazBC,CAAuB,CAAG,SAACC,CAAD,CAAY,CACxCF,CAAsB,CAACG,IAAvB,CAA4BD,CAA5B,EACA,GAAI,CAACH,CAAL,CAAqB,CACjBA,CAAc,CAAGK,WAAW,CAAC,UAAM,CAE/B,GAAMC,CAAAA,CAAK,CAAGC,QAAQ,CAACC,MAAT,CAAgBC,KAAhB,CAAsBC,CAAa,GAAK,GAAxC,CAAd,CACA,GAAoB,CAAhB,EAAAJ,CAAK,CAACK,MAAV,CAAuB,CAEnBC,CAAmB,GACnBC,aAAa,CAACb,CAAD,CAAb,CACAA,CAAc,CAAG,CAAjB,CAGAC,CAAsB,CAACa,OAAvB,CAA+B,SAACX,CAAD,CAAY,CACvCA,CAAM,CAACY,QAAP,GACH,CAFD,CAGH,CACJ,CAd2B,CAczB,GAdyB,CAe/B,CACJ,C,CAOKL,CAAa,CAAG,UAAM,CACxB,MAAO,kBAAoBM,CAAC,CAACC,GAAF,CAAMC,OACpC,C,CAKKN,CAAmB,CAAG,UAAM,CAC9BL,QAAQ,CAACC,MAAT,CAAkBW,kBAAkB,CAACT,CAAa,EAAd,CAAlB,CAAsC,oBAAtC,CAA6D,GAAIU,CAAAA,IAAJ,CAAS,CAAT,EAAYC,WAAZ,EAClF,C,QAOmB,QAAPC,CAAAA,IAAO,CAACC,CAAD,CAAe,CAC/B,GAAMpB,CAAAA,CAAM,CAAGI,QAAQ,CAACiB,cAAT,CAAwBD,CAAxB,CAAf,CAGAhB,QAAQ,CAACkB,gBAAT,CAA0BC,QAAMC,aAAhC,CAA+C,SAAAC,CAAC,CAAI,CAChDC,MAAM,CAACC,OAAP,CAAeC,GAAf,CAAmBH,CAAC,CAACI,MAArB,EACA7B,CAAM,CAACY,QAAP,GACH,CAHD,EAMAR,QAAQ,CAACkB,gBAAT,CAA0BC,QAAMO,eAAhC,CAAiD,SAAAL,CAAC,CAAI,CAClDC,MAAM,CAACC,OAAP,CAAeC,GAAf,CAAmBH,CAAC,CAACI,MAArB,EACA7B,CAAM,CAACY,QAAP,GACH,CAHD,EAMA,GAAmD,KAA/C,GAAAZ,CAAM,CAAC+B,IAAP,CAAYC,OAAZ,CAAoBC,sBAAxB,CAA0D,CACtD,MACH,CACDjC,CAAM,CAAC+B,IAAP,CAAYT,gBAAZ,CAA6B,QAA7B,CAAuC,SAASY,CAAT,CAAgB,CAGnD,GAAMC,CAAAA,CAAa,CAAG,UAAW,CAE7B,GAAID,CAAK,CAACE,gBAAN,EAA0BpC,CAAM,CAACY,QAArC,CAA+C,CAC3C,MACH,CAEDZ,CAAM,CAACY,QAAP,IACAH,CAAmB,GACnBV,CAAuB,CAACC,CAAD,CAC1B,CATD,CAUA0B,MAAM,CAACJ,gBAAP,CAAwB,cAAxB,CAAwCa,CAAxC,EAIAE,UAAU,CAAC,UAAW,CAClBX,MAAM,CAACY,mBAAP,CAA2B,cAA3B,CAA2CH,CAA3C,CACH,CAFS,CAEP,CAFO,CAGb,CApBD,IAqBH,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Submit button JavaScript. All submit buttons will be automatically disabled once the form is\n * submitted, unless that submission results in an error/cancelling the submit.\n *\n * @module core_form/submit\n * @package core_form\n * @copyright 2019 The Open University\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.8\n */\n\nimport {types} from 'core_form/events';\n\n/** @type {number} ID for setInterval used when polling for download cookie */\nlet cookieListener = 0;\n\n/** @type {Array} Array of buttons that need re-enabling if we get a download cookie */\nconst cookieListeningButtons = [];\n\n/**\n * Listens in case a download cookie is provided.\n *\n * This function is used to detect file downloads. If there is a file download then we get a\n * beforeunload event, but the page is never unloaded and when the file download completes we\n * should re-enable the buttons. We detect this by watching for a specific cookie.\n *\n * PHP function \\core_form\\util::form_download_complete() can be used to send this cookie.\n *\n * @param {HTMLElement} button Button to re-enable\n */\nconst listenForDownloadCookie = (button) => {\n cookieListeningButtons.push(button);\n if (!cookieListener) {\n cookieListener = setInterval(() => {\n // Look for cookie.\n const parts = document.cookie.split(getCookieName() + '=');\n if (parts.length == 2) {\n // We found the cookie, so the file is ready. Expire the cookie and cancel polling.\n clearDownloadCookie();\n clearInterval(cookieListener);\n cookieListener = 0;\n\n // Re-enable all the buttons.\n cookieListeningButtons.forEach((button) => {\n button.disabled = false;\n });\n }\n }, 500);\n }\n};\n\n/**\n * Gets a unique name for the download cookie.\n *\n * @returns {string} Cookie name\n */\nconst getCookieName = () => {\n return 'moodledownload_' + M.cfg.sesskey;\n};\n\n/**\n * Clears the download cookie if there is one.\n */\nconst clearDownloadCookie = () => {\n document.cookie = encodeURIComponent(getCookieName()) + '=deleted; expires=' + new Date(0).toUTCString();\n};\n\n/**\n * Initialises submit buttons.\n *\n * @param {String} elementId Form element\n */\nexport const init = (elementId) => {\n const button = document.getElementById(elementId);\n\n // Add event listener for file upload start.\n document.addEventListener(types.uploadStarted, e => {\n window.console.log(e.target); // This will be the element/section where the file is uploaded to.\n button.disabled = true;\n });\n\n // Add event listener for file upload complete.\n document.addEventListener(types.uploadCompleted, e => {\n window.console.log(e.target); // This will be the element/section where the file is uploaded to.\n button.disabled = false;\n });\n\n // If the form has double submit protection disabled, do nothing.\n if (button.form.dataset.doubleSubmitProtection === 'off') {\n return;\n }\n button.form.addEventListener('submit', function(event) {\n // Only disable it if the browser is really going to another page as a result of the\n // submit.\n const disableAction = function() {\n // If the submit was cancelled, or the button is already disabled, don't do anything.\n if (event.defaultPrevented || button.disabled) {\n return;\n }\n\n button.disabled = true;\n clearDownloadCookie();\n listenForDownloadCookie(button);\n };\n window.addEventListener('beforeunload', disableAction);\n // If there is no beforeunload event as a result of this form submit, then the form\n // submit must have been cancelled, so don't disable the button if the page is\n // unloaded later.\n setTimeout(function() {\n window.removeEventListener('beforeunload', disableAction);\n }, 0);\n }, false);\n};\n"],"file":"submit.min.js"}
\ No newline at end of file
diff --git a/lib/form/amd/src/events.js b/lib/form/amd/src/events.js
new file mode 100644
index 00000000000..87faeb77bd4
--- /dev/null
+++ b/lib/form/amd/src/events.js
@@ -0,0 +1,88 @@
+// 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 .
+
+/**
+ * Contain the events the form component can trigger.
+ *
+ * @module core_form/events
+ * @package core_form
+ * @copyright 2021 Huong Nguyen
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since 3.10
+ */
+
+import {get_string as getString} from 'core/str';
+
+let changesMadeString;
+getString('changesmadereallygoaway', 'moodle').then(string => {
+ changesMadeString = string;
+ return string;
+}).catch();
+
+/**
+ * Prevent user navigate away when upload progress still running.
+ * @param {Event} e The event
+ */
+const changesMadeCheck = e => {
+ if (e) {
+ e.returnValue = changesMadeString;
+ }
+};
+
+/**
+ * List of the events.
+ **/
+export const types = {
+ uploadStarted: 'core_form/uploadStarted',
+ uploadCompleted: 'core_form/uploadCompleted',
+};
+
+/**
+ * Trigger upload start event.
+ *
+ * @param {String} elementId
+ * @returns {CustomEvent}
+ */
+export const triggerUploadStarted = elementId => {
+ // Add an additional check for changes made.
+ window.addEventListener('beforeunload', changesMadeCheck);
+ const customEvent = new CustomEvent(types.uploadStarted, {
+ bubbles: true,
+ cancellable: false
+ });
+ const element = document.getElementById(elementId);
+ element.dispatchEvent(customEvent);
+
+ return customEvent;
+};
+
+/**
+ * Trigger upload complete event.
+ *
+ * @param {String} elementId
+ * @returns {CustomEvent}
+ */
+export const triggerUploadCompleted = elementId => {
+ // Remove the additional check for changes made.
+ window.removeEventListener('beforeunload', changesMadeCheck);
+ const customEvent = new CustomEvent(types.uploadCompleted, {
+ bubbles: true,
+ cancellable: false
+ });
+ const element = document.getElementById(elementId);
+ element.dispatchEvent(customEvent);
+
+ return customEvent;
+};
diff --git a/lib/form/amd/src/submit.js b/lib/form/amd/src/submit.js
index af4271ec75b..677cb39805c 100644
--- a/lib/form/amd/src/submit.js
+++ b/lib/form/amd/src/submit.js
@@ -24,6 +24,8 @@
* @since 3.8
*/
+import {types} from 'core_form/events';
+
/** @type {number} ID for setInterval used when polling for download cookie */
let cookieListener = 0;
@@ -85,6 +87,19 @@ const clearDownloadCookie = () => {
*/
export const init = (elementId) => {
const button = document.getElementById(elementId);
+
+ // Add event listener for file upload start.
+ document.addEventListener(types.uploadStarted, e => {
+ window.console.log(e.target); // This will be the element/section where the file is uploaded to.
+ button.disabled = true;
+ });
+
+ // Add event listener for file upload complete.
+ document.addEventListener(types.uploadCompleted, e => {
+ window.console.log(e.target); // This will be the element/section where the file is uploaded to.
+ button.disabled = false;
+ });
+
// If the form has double submit protection disabled, do nothing.
if (button.form.dataset.doubleSubmitProtection === 'off') {
return;
diff --git a/lib/form/dndupload.js b/lib/form/dndupload.js
index fc073fe2744..6d7063d4704 100644
--- a/lib/form/dndupload.js
+++ b/lib/form/dndupload.js
@@ -504,8 +504,8 @@ M.form_dndupload.init = function(Y, options) {
overwriteall: false,
// Set to true if the user has clicked on 'rename all'.
renameall: false,
- // Original onbeforeunload event.
- originalUnloadEvent: null,
+ // The file manager helper.
+ filemanagerhelper: null,
/**
* Initialise the settings for the dnduploader
@@ -527,6 +527,7 @@ M.form_dndupload.init = function(Y, options) {
this.currentfiles = params.currentfiles;
this.currentfilecount = params.currentfilecount;
this.currentareasize = 0;
+ this.filemanagerhelper = this.options.filemanager;
// Retrieve the current size of the area.
for (var i = 0; i < this.currentfiles.length; i++) {
@@ -538,8 +539,11 @@ M.form_dndupload.init = function(Y, options) {
this.callbackcancel();
}
}
- this.originalUnloadEvent = window.onbeforeunload;
- this.reportUploadDirtyState(true);
+
+ // Trigger form upload start events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadStarted(this.filemanagerhelper.filemanager.get('id'));
+ }.bind(this));
},
/**
@@ -852,7 +856,10 @@ M.form_dndupload.init = function(Y, options) {
* Run the callback to the filemanager/filepicker
*/
uploadfinished: function(lastresult) {
- this.reportUploadDirtyState(false);
+ // Trigger form upload complete events.
+ require(['core_form/events'], function(FormEvent) {
+ FormEvent.triggerUploadCompleted(this.filemanagerhelper.filemanager.get('id'));
+ }.bind(this));
this.callback(lastresult);
},
@@ -952,25 +959,6 @@ M.form_dndupload.init = function(Y, options) {
xhr.open("POST", uploadUrl, true);
xhr.send(formdata);
return true;
- },
-
- /**
- * Set the event to prevent user navigate away when upload progress still running.
- *
- * @param {bool} enable true if upload progress is running, false otherwise
- */
- reportUploadDirtyState: function(enable) {
- if (!enable) {
- window.onbeforeunload = this.originalUnloadEvent;
- } else {
- window.onbeforeunload = function(e) {
- var warningMessage = M.util.get_string('changesmadereallygoaway', 'moodle');
- if (e) {
- e.returnValue = warningMessage;
- }
- return warningMessage;
- };
- }
}
});