diff --git a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js index 2cdfc6ab0b3..e3be3c48c58 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js +++ b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js @@ -1,10 +1,10 @@ -define("tiny_autosave/autosaver",["exports","./options","./storage","core/log","./common"],(function(_exports,Options,Storage,_log,_common){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj} +define("tiny_autosave/autosaver",["exports","./options","./storage","core/log","core_form/events","./common"],(function(_exports,Options,Storage,_log,_events,_common){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj} /** * Storage helper for the Moodle Tiny Autosave plugin. * * @module tiny_autosave/plugin * @copyright 2022 Andrew Lyons <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.register=void 0,Options=_interopRequireWildcard(Options),Storage=_interopRequireWildcard(Storage),_log=(obj=_log)&&obj.__esModule?obj:{default:obj};_exports.register=editor=>{const undoHandler=()=>{editor.undoManager.hasUndo()?Storage.saveDraft(editor):_log.default.debug("Ignoring undo event as there is no undo history",(0,_common.getLogSource)(editor))},visibilityChangedHandler=()=>{"hidden"===document.visibilityState&&Options.isInitialised(editor)&&Storage.saveDraft(editor)};document.addEventListener("visibilitychange",visibilityChangedHandler),editor.on("submit",(()=>{document.removeEventListener("visibilitychange",visibilityChangedHandler),Storage.removeAutosaveSession(editor)})),editor.on("init",(()=>{editor.on("AddUndo",undoHandler),editor.dom.isEmpty(editor.getBody())?(_log.default.info("Attempting to restore draft",(0,_common.getLogSource)(editor)),Storage.restoreDraft(editor)):(_log.default.warn("Skipping draft restoration. The editor is not empty.",(0,_common.getLogSource)(editor)),Options.markInitialised(editor))}))}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.register=void 0,Options=_interopRequireWildcard(Options),Storage=_interopRequireWildcard(Storage),_log=(obj=_log)&&obj.__esModule?obj:{default:obj};_exports.register=editor=>{const undoHandler=()=>{editor.undoManager.hasUndo()?Storage.saveDraft(editor):_log.default.debug("Ignoring undo event as there is no undo history",(0,_common.getLogSource)(editor))},visibilityChangedHandler=()=>{"hidden"===document.visibilityState&&Options.isInitialised(editor)&&Storage.saveDraft(editor)},handleFormSubmittedByJavascript=e=>{Options.isInitialised(editor)&&e.target.contains(editor.getElement())&&removeAutoSaveSession()},removeAutoSaveSession=()=>{document.removeEventListener("visibilitychange",visibilityChangedHandler),document.removeEventListener(_events.eventTypes.formSubmittedByJavascript,handleFormSubmittedByJavascript),Storage.removeAutosaveSession(editor)};document.addEventListener("visibilitychange",visibilityChangedHandler),editor.on("submit",removeAutoSaveSession),document.addEventListener(_events.eventTypes.formSubmittedByJavascript,handleFormSubmittedByJavascript),editor.on("init",(()=>{editor.on("AddUndo",undoHandler),editor.dom.isEmpty(editor.getBody())?(_log.default.info("Attempting to restore draft",(0,_common.getLogSource)(editor)),Storage.restoreDraft(editor)):(_log.default.warn("Skipping draft restoration. The editor is not empty.",(0,_common.getLogSource)(editor)),Options.markInitialised(editor))}))}})); //# sourceMappingURL=autosaver.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map index 9fb5152ac8c..ec8c04ba3c7 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map +++ b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map @@ -1 +1 @@ -{"version":3,"file":"autosaver.min.js","sources":["../src/autosaver.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Storage helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/plugin\n * @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Options from './options';\nimport * as Storage from './storage';\nimport Log from 'core/log';\nimport {getLogSource} from './common';\n\nexport const register = (editor) => {\n const undoHandler = () => {\n if (!editor.undoManager.hasUndo()) {\n Log.debug(`Ignoring undo event as there is no undo history`, getLogSource(editor));\n return;\n }\n Storage.saveDraft(editor);\n };\n\n const visibilityChangedHandler = () => {\n if (document.visibilityState === 'hidden') {\n if (Options.isInitialised(editor)) {\n Storage.saveDraft(editor);\n }\n }\n };\n\n // Attempt to store the draft one final time before the page unloads.\n // Note: This may need to be sent as a beacon instead.\n document.addEventListener('visibilitychange', visibilityChangedHandler);\n\n // When the page is submitted as a form, remove the draft.\n editor.on('submit', () => {\n document.removeEventListener('visibilitychange', visibilityChangedHandler);\n Storage.removeAutosaveSession(editor);\n });\n\n editor.on('init', () => {\n // Setup the Undo handler.\n editor.on('AddUndo', undoHandler);\n\n if (editor.dom.isEmpty(editor.getBody())) {\n Log.info(`Attempting to restore draft`, getLogSource(editor));\n Storage.restoreDraft(editor);\n } else {\n // There was nothing to restore, so we can mark the editor as initialised.\n Log.warn(`Skipping draft restoration. The editor is not empty.`, getLogSource(editor));\n Options.markInitialised(editor);\n }\n });\n};\n"],"names":["editor","undoHandler","undoManager","hasUndo","Storage","saveDraft","debug","visibilityChangedHandler","document","visibilityState","Options","isInitialised","addEventListener","on","removeEventListener","removeAutosaveSession","dom","isEmpty","getBody","info","restoreDraft","warn","markInitialised"],"mappings":";;;;;;;4OA4ByBA,eACfC,YAAc,KACXD,OAAOE,YAAYC,UAIxBC,QAAQC,UAAUL,qBAHVM,yDAAyD,wBAAaN,UAM5EO,yBAA2B,KACI,WAA7BC,SAASC,iBACLC,QAAQC,cAAcX,SACtBI,QAAQC,UAAUL,SAO9BQ,SAASI,iBAAiB,mBAAoBL,0BAG9CP,OAAOa,GAAG,UAAU,KAChBL,SAASM,oBAAoB,mBAAoBP,0BACjDH,QAAQW,sBAAsBf,WAGlCA,OAAOa,GAAG,QAAQ,KAEdb,OAAOa,GAAG,UAAWZ,aAEjBD,OAAOgB,IAAIC,QAAQjB,OAAOkB,yBACtBC,oCAAoC,wBAAanB,SACrDI,QAAQgB,aAAapB,uBAGjBqB,6DAA6D,wBAAarB,SAC9EU,QAAQY,gBAAgBtB"} \ No newline at end of file +{"version":3,"file":"autosaver.min.js","sources":["../src/autosaver.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Storage helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/plugin\n * @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Options from './options';\nimport * as Storage from './storage';\nimport Log from 'core/log';\nimport {eventTypes} from 'core_form/events';\nimport {getLogSource} from './common';\n\nexport const register = (editor) => {\n const undoHandler = () => {\n if (!editor.undoManager.hasUndo()) {\n Log.debug(`Ignoring undo event as there is no undo history`, getLogSource(editor));\n return;\n }\n Storage.saveDraft(editor);\n };\n\n const visibilityChangedHandler = () => {\n if (document.visibilityState === 'hidden') {\n if (Options.isInitialised(editor)) {\n Storage.saveDraft(editor);\n }\n }\n };\n\n // Javascript form submission handler.\n const handleFormSubmittedByJavascript = (e) => {\n if (Options.isInitialised(editor) && e.target.contains(editor.getElement())) {\n removeAutoSaveSession();\n }\n };\n\n // Remove the auto save session.\n const removeAutoSaveSession = () => {\n document.removeEventListener('visibilitychange', visibilityChangedHandler);\n document.removeEventListener(eventTypes.formSubmittedByJavascript, handleFormSubmittedByJavascript);\n Storage.removeAutosaveSession(editor);\n };\n\n // Attempt to store the draft one final time before the page unloads.\n // Note: This may need to be sent as a beacon instead.\n document.addEventListener('visibilitychange', visibilityChangedHandler);\n\n // When the page is submitted as a form, remove the draft.\n editor.on('submit', removeAutoSaveSession);\n document.addEventListener(eventTypes.formSubmittedByJavascript, handleFormSubmittedByJavascript);\n\n editor.on('init', () => {\n // Setup the Undo handler.\n editor.on('AddUndo', undoHandler);\n\n if (editor.dom.isEmpty(editor.getBody())) {\n Log.info(`Attempting to restore draft`, getLogSource(editor));\n Storage.restoreDraft(editor);\n } else {\n // There was nothing to restore, so we can mark the editor as initialised.\n Log.warn(`Skipping draft restoration. The editor is not empty.`, getLogSource(editor));\n Options.markInitialised(editor);\n }\n });\n};\n"],"names":["editor","undoHandler","undoManager","hasUndo","Storage","saveDraft","debug","visibilityChangedHandler","document","visibilityState","Options","isInitialised","handleFormSubmittedByJavascript","e","target","contains","getElement","removeAutoSaveSession","removeEventListener","eventTypes","formSubmittedByJavascript","removeAutosaveSession","addEventListener","on","dom","isEmpty","getBody","info","restoreDraft","warn","markInitialised"],"mappings":";;;;;;;4OA6ByBA,eACfC,YAAc,KACXD,OAAOE,YAAYC,UAIxBC,QAAQC,UAAUL,qBAHVM,yDAAyD,wBAAaN,UAM5EO,yBAA2B,KACI,WAA7BC,SAASC,iBACLC,QAAQC,cAAcX,SACtBI,QAAQC,UAAUL,SAMxBY,gCAAmCC,IACjCH,QAAQC,cAAcX,SAAWa,EAAEC,OAAOC,SAASf,OAAOgB,eAC1DC,yBAKFA,sBAAwB,KAC1BT,SAASU,oBAAoB,mBAAoBX,0BACjDC,SAASU,oBAAoBC,mBAAWC,0BAA2BR,iCACnER,QAAQiB,sBAAsBrB,SAKlCQ,SAASc,iBAAiB,mBAAoBf,0BAG9CP,OAAOuB,GAAG,SAAUN,uBACpBT,SAASc,iBAAiBH,mBAAWC,0BAA2BR,iCAEhEZ,OAAOuB,GAAG,QAAQ,KAEdvB,OAAOuB,GAAG,UAAWtB,aAEjBD,OAAOwB,IAAIC,QAAQzB,OAAO0B,yBACtBC,oCAAoC,wBAAa3B,SACrDI,QAAQwB,aAAa5B,uBAGjB6B,6DAA6D,wBAAa7B,SAC9EU,QAAQoB,gBAAgB9B"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js b/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js index 194a27a2238..9d58a6c0055 100644 --- a/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js +++ b/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js @@ -24,6 +24,7 @@ import * as Options from './options'; import * as Storage from './storage'; import Log from 'core/log'; +import {eventTypes} from 'core_form/events'; import {getLogSource} from './common'; export const register = (editor) => { @@ -43,15 +44,27 @@ export const register = (editor) => { } }; + // Javascript form submission handler. + const handleFormSubmittedByJavascript = (e) => { + if (Options.isInitialised(editor) && e.target.contains(editor.getElement())) { + removeAutoSaveSession(); + } + }; + + // Remove the auto save session. + const removeAutoSaveSession = () => { + document.removeEventListener('visibilitychange', visibilityChangedHandler); + document.removeEventListener(eventTypes.formSubmittedByJavascript, handleFormSubmittedByJavascript); + Storage.removeAutosaveSession(editor); + }; + // Attempt to store the draft one final time before the page unloads. // Note: This may need to be sent as a beacon instead. document.addEventListener('visibilitychange', visibilityChangedHandler); // When the page is submitted as a form, remove the draft. - editor.on('submit', () => { - document.removeEventListener('visibilitychange', visibilityChangedHandler); - Storage.removeAutosaveSession(editor); - }); + editor.on('submit', removeAutoSaveSession); + document.addEventListener(eventTypes.formSubmittedByJavascript, handleFormSubmittedByJavascript); editor.on('init', () => { // Setup the Undo handler. diff --git a/lib/editor/tiny/plugins/autosave/tests/behat/autosave.feature b/lib/editor/tiny/plugins/autosave/tests/behat/autosave.feature index 32449db5076..9edd046cd52 100644 --- a/lib/editor/tiny/plugins/autosave/tests/behat/autosave.feature +++ b/lib/editor/tiny/plugins/autosave/tests/behat/autosave.feature @@ -17,8 +17,8 @@ Feature: Tiny editor autosave | teacher1 | C1 | editingteacher | | teacher2 | C1 | editingteacher | And the following "blocks" exist: - | blockname | contextlevel | reference | pagetypepattern | defaultregion | - | private_files | System | 1 | my-index | side-post | + | blockname | contextlevel | reference | pagetypepattern | defaultregion | + | private_files | System | 1 | my-index | side-post | @javascript Scenario: Restore a draft on user profile page @@ -69,3 +69,16 @@ Feature: Tiny editor autosave And I navigate to "Settings" in current page administration Then I should not see "This is my draft" in the "#id_summary_editor" "css_element" And the field "Course summary" matches value "<p>Modified text</p>" + + @javascript + Scenario: Draft should not be restored if the form was submitted via Javascript + Given I am on the "Course 1" course page logged in as teacher1 + And I follow "Calendar" in the user menu + And I click on "New event" "button" + And I click on "Show more..." "link" in the "New event" "dialogue" + And I set the field "Event title" to "Test course event" + And I set the field "Description" to "This is my draft" + And I click on "Save" "button" + And I click on "New event" "button" + When I click on "Show more..." "link" in the "New event" "dialogue" + Then the field "Description" matches value ""