From 2ac0df331c6ee365b0bb4b56be7293ac49703565 Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Wed, 20 Sep 2023 23:00:32 +0100 Subject: [PATCH 1/2] MDL-72308 mod_forum: update legacy uses of formchangechecker module. --- mod/forum/amd/build/discussion_list.min.js | 2 +- mod/forum/amd/build/discussion_list.min.js.map | 2 +- mod/forum/amd/build/inpage_reply.min.js | 2 +- mod/forum/amd/build/inpage_reply.min.js.map | 2 +- mod/forum/amd/src/discussion_list.js | 10 +++++----- mod/forum/amd/src/inpage_reply.js | 6 ++---- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/mod/forum/amd/build/discussion_list.min.js b/mod/forum/amd/build/discussion_list.min.js index 5cd9d474bb6..858e5967c24 100644 --- a/mod/forum/amd/build/discussion_list.min.js +++ b/mod/forum/amd/build/discussion_list.min.js @@ -5,6 +5,6 @@ * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("mod_forum/discussion_list",["jquery","core/templates","core/str","core/notification","mod_forum/subscription_toggle","mod_forum/selectors","mod_forum/repository","core/pubsub","mod_forum/forum_events"],(function($,Templates,Str,Notification,SubscriptionToggle,Selectors,Repository,PubSub,ForumEvents){return{init:function(root){SubscriptionToggle.init(root,!1,(function(toggleElement,context){var toggleId=toggleElement.attr("id"),newTargetState=context.userstate.subscribed?0:1;toggleElement.data("targetstate",newTargetState);var stringKey=context.userstate.subscribed?"unsubscribediscussion":"subscribediscussion";return Str.get_string(stringKey,"mod_forum").then((function(string){return toggleElement.closest("td").find('label[for="'+toggleId+'"]').find("span").text(string),string}))})),function(root){PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED,(function(data){var discussionId=data.discussionId,subscribed=data.subscriptionState,discussionListItem=root.find(Selectors.discussion.item+"[data-discussionid= "+discussionId+"]"),subscribedLabel=discussionListItem.find(Selectors.discussion.subscribedLabel);subscribed?(discussionListItem.addClass("subscribed"),subscribedLabel.removeAttr("hidden")):(discussionListItem.removeClass("subscribed"),subscribedLabel.attr("hidden",!0))})),root.on("click",Selectors.post.inpageCancelButton,(function(){void 0!==M.core_formchangechecker&&M.core_formchangechecker.reset_form_dirty_state()})),root.on("click",Selectors.favourite.toggle,(function(e){e.preventDefault();var toggleElement=$(this),forumId=toggleElement.data("forumid"),discussionId=toggleElement.data("discussionid"),subscriptionState=toggleElement.data("targetstate");Repository.setFavouriteDiscussionState(forumId,discussionId,subscriptionState).then((function(){return location.reload()})).catch(Notification.exception)})),root.on("click",Selectors.pin.toggle,(function(e){e.preventDefault();var toggleElement=$(this),forumId=toggleElement.data("forumid"),discussionId=toggleElement.data("discussionid"),state=toggleElement.data("targetstate");Repository.setPinDiscussionState(forumId,discussionId,state).then((function(){return location.reload()})).catch(Notification.exception)})),root.on("click",Selectors.lock.toggle,(function(e){var toggleElement=$(this),forumId=toggleElement.data("forumid"),discussionId=toggleElement.data("discussionid"),state=toggleElement.data("state");Repository.setDiscussionLockState(forumId,discussionId,state).then((function(context){var icon=toggleElement.parents(Selectors.summary.actions).find(Selectors.lock.icon),lockedLabel=toggleElement.parents(Selectors.discussion.item).find(Selectors.discussion.lockedLabel);return context.locked?(icon.removeClass("hidden"),lockedLabel.removeAttr("hidden")):(icon.addClass("hidden"),lockedLabel.attr("hidden",!0)),context})).then((function(context){return context.forumid=forumId,Templates.render("mod_forum/discussion_lock_toggle",context)})).then((function(html,js){return Templates.replaceNode(toggleElement,html,js)})).then((function(){return Str.get_string("lockupdated","forum").done((function(s){return Notification.addNotification({message:s,type:"info"})}))})).catch(Notification.exception),e.preventDefault()}))}(root)}}})); +define("mod_forum/discussion_list",["jquery","core/templates","core/str","core/notification","mod_forum/subscription_toggle","mod_forum/selectors","mod_forum/repository","core/pubsub","mod_forum/forum_events","core_form/changechecker"],(function($,Templates,Str,Notification,SubscriptionToggle,Selectors,Repository,PubSub,ForumEvents,FormChangeChecker){return{init:function(root){SubscriptionToggle.init(root,!1,(function(toggleElement,context){var toggleId=toggleElement.attr("id"),newTargetState=context.userstate.subscribed?0:1;toggleElement.data("targetstate",newTargetState);var stringKey=context.userstate.subscribed?"unsubscribediscussion":"subscribediscussion";return Str.get_string(stringKey,"mod_forum").then((function(string){return toggleElement.closest("td").find('label[for="'+toggleId+'"]').find("span").text(string),string}))})),function(root){PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED,(function(data){var discussionId=data.discussionId,subscribed=data.subscriptionState,discussionListItem=root.find(Selectors.discussion.item+"[data-discussionid= "+discussionId+"]"),subscribedLabel=discussionListItem.find(Selectors.discussion.subscribedLabel);subscribed?(discussionListItem.addClass("subscribed"),subscribedLabel.removeAttr("hidden")):(discussionListItem.removeClass("subscribed"),subscribedLabel.attr("hidden",!0))})),root.on("click",Selectors.post.inpageCancelButton,(function(e){FormChangeChecker.resetFormDirtyState(e.currentTarget)})),root.on("click",Selectors.favourite.toggle,(function(e){e.preventDefault();var toggleElement=$(this),forumId=toggleElement.data("forumid"),discussionId=toggleElement.data("discussionid"),subscriptionState=toggleElement.data("targetstate");Repository.setFavouriteDiscussionState(forumId,discussionId,subscriptionState).then((function(){return location.reload()})).catch(Notification.exception)})),root.on("click",Selectors.pin.toggle,(function(e){e.preventDefault();var toggleElement=$(this),forumId=toggleElement.data("forumid"),discussionId=toggleElement.data("discussionid"),state=toggleElement.data("targetstate");Repository.setPinDiscussionState(forumId,discussionId,state).then((function(){return location.reload()})).catch(Notification.exception)})),root.on("click",Selectors.lock.toggle,(function(e){var toggleElement=$(this),forumId=toggleElement.data("forumid"),discussionId=toggleElement.data("discussionid"),state=toggleElement.data("state");Repository.setDiscussionLockState(forumId,discussionId,state).then((function(context){var icon=toggleElement.parents(Selectors.summary.actions).find(Selectors.lock.icon),lockedLabel=toggleElement.parents(Selectors.discussion.item).find(Selectors.discussion.lockedLabel);return context.locked?(icon.removeClass("hidden"),lockedLabel.removeAttr("hidden")):(icon.addClass("hidden"),lockedLabel.attr("hidden",!0)),context})).then((function(context){return context.forumid=forumId,Templates.render("mod_forum/discussion_lock_toggle",context)})).then((function(html,js){return Templates.replaceNode(toggleElement,html,js)})).then((function(){return Str.get_string("lockupdated","forum").done((function(s){return Notification.addNotification({message:s,type:"info"})}))})).catch(Notification.exception),e.preventDefault()}))}(root)}}})); //# sourceMappingURL=discussion_list.min.js.map \ No newline at end of file diff --git a/mod/forum/amd/build/discussion_list.min.js.map b/mod/forum/amd/build/discussion_list.min.js.map index eac4c3ab170..93dcd8126e2 100644 --- a/mod/forum/amd/build/discussion_list.min.js.map +++ b/mod/forum/amd/build/discussion_list.min.js.map @@ -1 +1 @@ -{"version":3,"file":"discussion_list.min.js","sources":["../src/discussion_list.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module for the list of discussions on when viewing a forum.\n *\n * @module mod_forum/discussion_list\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/str',\n 'core/notification',\n 'mod_forum/subscription_toggle',\n 'mod_forum/selectors',\n 'mod_forum/repository',\n 'core/pubsub',\n 'mod_forum/forum_events',\n], function(\n $,\n Templates,\n Str,\n Notification,\n SubscriptionToggle,\n Selectors,\n Repository,\n PubSub,\n ForumEvents\n) {\n var registerEventListeners = function(root) {\n PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED, function(data) {\n var discussionId = data.discussionId;\n var subscribed = data.subscriptionState;\n var discussionListItem = root.find(Selectors.discussion.item + '[data-discussionid= ' + discussionId + ']');\n var subscribedLabel = discussionListItem.find(Selectors.discussion.subscribedLabel);\n if (subscribed) {\n discussionListItem.addClass('subscribed');\n subscribedLabel.removeAttr('hidden');\n } else {\n discussionListItem.removeClass('subscribed');\n subscribedLabel.attr('hidden', true);\n }\n });\n\n root.on('click', Selectors.post.inpageCancelButton, function() {\n // Tell formchangechecker to reset the form state.\n if (typeof M.core_formchangechecker !== 'undefined') {\n M.core_formchangechecker.reset_form_dirty_state();\n }\n });\n\n root.on('click', Selectors.favourite.toggle, function(e) {\n e.preventDefault();\n\n var toggleElement = $(this);\n var forumId = toggleElement.data('forumid');\n var discussionId = toggleElement.data('discussionid');\n var subscriptionState = toggleElement.data('targetstate');\n Repository.setFavouriteDiscussionState(forumId, discussionId, subscriptionState)\n .then(function() {\n return location.reload();\n })\n .catch(Notification.exception);\n });\n\n root.on('click', Selectors.pin.toggle, function(e) {\n e.preventDefault();\n var toggleElement = $(this);\n var forumId = toggleElement.data('forumid');\n var discussionId = toggleElement.data('discussionid');\n var state = toggleElement.data('targetstate');\n Repository.setPinDiscussionState(forumId, discussionId, state)\n .then(function() {\n return location.reload();\n })\n .catch(Notification.exception);\n });\n\n root.on('click', Selectors.lock.toggle, function(e) {\n var toggleElement = $(this);\n var forumId = toggleElement.data('forumid');\n var discussionId = toggleElement.data('discussionid');\n var state = toggleElement.data('state');\n\n Repository.setDiscussionLockState(forumId, discussionId, state)\n .then(function(context) {\n var icon = toggleElement.parents(Selectors.summary.actions).find(Selectors.lock.icon);\n var lockedLabel = toggleElement.parents(Selectors.discussion.item).find(Selectors.discussion.lockedLabel);\n if (context.locked) {\n icon.removeClass('hidden');\n lockedLabel.removeAttr('hidden');\n } else {\n icon.addClass('hidden');\n lockedLabel.attr('hidden', true);\n }\n return context;\n })\n .then(function(context) {\n context.forumid = forumId;\n return Templates.render('mod_forum/discussion_lock_toggle', context);\n })\n .then(function(html, js) {\n return Templates.replaceNode(toggleElement, html, js);\n })\n .then(function() {\n return Str.get_string('lockupdated', 'forum')\n .done(function(s) {\n return Notification.addNotification({\n message: s,\n type: \"info\"\n });\n });\n })\n .catch(Notification.exception);\n\n e.preventDefault();\n });\n };\n\n return {\n init: function(root) {\n SubscriptionToggle.init(root, false, function(toggleElement, context) {\n var toggleId = toggleElement.attr('id');\n var newTargetState = context.userstate.subscribed ? 0 : 1;\n toggleElement.data('targetstate', newTargetState);\n\n var stringKey = context.userstate.subscribed ? 'unsubscribediscussion' : 'subscribediscussion';\n return Str.get_string(stringKey, 'mod_forum')\n .then(function(string) {\n toggleElement.closest('td').find('label[for=\"' + toggleId + '\"]').find('span').text(string);\n return string;\n });\n });\n registerEventListeners(root);\n }\n };\n});\n"],"names":["define","$","Templates","Str","Notification","SubscriptionToggle","Selectors","Repository","PubSub","ForumEvents","init","root","toggleElement","context","toggleId","attr","newTargetState","userstate","subscribed","data","stringKey","get_string","then","string","closest","find","text","subscribe","SUBSCRIPTION_TOGGLED","discussionId","subscriptionState","discussionListItem","discussion","item","subscribedLabel","addClass","removeAttr","removeClass","on","post","inpageCancelButton","M","core_formchangechecker","reset_form_dirty_state","favourite","toggle","e","preventDefault","this","forumId","setFavouriteDiscussionState","location","reload","catch","exception","pin","state","setPinDiscussionState","lock","setDiscussionLockState","icon","parents","summary","actions","lockedLabel","locked","forumid","render","html","js","replaceNode","done","s","addNotification","message","type","registerEventListeners"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"discussion_list.min.js","sources":["../src/discussion_list.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module for the list of discussions on when viewing a forum.\n *\n * @module mod_forum/discussion_list\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/str',\n 'core/notification',\n 'mod_forum/subscription_toggle',\n 'mod_forum/selectors',\n 'mod_forum/repository',\n 'core/pubsub',\n 'mod_forum/forum_events',\n 'core_form/changechecker',\n], function(\n $,\n Templates,\n Str,\n Notification,\n SubscriptionToggle,\n Selectors,\n Repository,\n PubSub,\n ForumEvents,\n FormChangeChecker\n) {\n var registerEventListeners = function(root) {\n PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED, function(data) {\n var discussionId = data.discussionId;\n var subscribed = data.subscriptionState;\n var discussionListItem = root.find(Selectors.discussion.item + '[data-discussionid= ' + discussionId + ']');\n var subscribedLabel = discussionListItem.find(Selectors.discussion.subscribedLabel);\n if (subscribed) {\n discussionListItem.addClass('subscribed');\n subscribedLabel.removeAttr('hidden');\n } else {\n discussionListItem.removeClass('subscribed');\n subscribedLabel.attr('hidden', true);\n }\n });\n\n root.on('click', Selectors.post.inpageCancelButton, function(e) {\n // Tell formchangechecker to reset the form state.\n FormChangeChecker.resetFormDirtyState(e.currentTarget);\n });\n\n root.on('click', Selectors.favourite.toggle, function(e) {\n e.preventDefault();\n\n var toggleElement = $(this);\n var forumId = toggleElement.data('forumid');\n var discussionId = toggleElement.data('discussionid');\n var subscriptionState = toggleElement.data('targetstate');\n Repository.setFavouriteDiscussionState(forumId, discussionId, subscriptionState)\n .then(function() {\n return location.reload();\n })\n .catch(Notification.exception);\n });\n\n root.on('click', Selectors.pin.toggle, function(e) {\n e.preventDefault();\n var toggleElement = $(this);\n var forumId = toggleElement.data('forumid');\n var discussionId = toggleElement.data('discussionid');\n var state = toggleElement.data('targetstate');\n Repository.setPinDiscussionState(forumId, discussionId, state)\n .then(function() {\n return location.reload();\n })\n .catch(Notification.exception);\n });\n\n root.on('click', Selectors.lock.toggle, function(e) {\n var toggleElement = $(this);\n var forumId = toggleElement.data('forumid');\n var discussionId = toggleElement.data('discussionid');\n var state = toggleElement.data('state');\n\n Repository.setDiscussionLockState(forumId, discussionId, state)\n .then(function(context) {\n var icon = toggleElement.parents(Selectors.summary.actions).find(Selectors.lock.icon);\n var lockedLabel = toggleElement.parents(Selectors.discussion.item).find(Selectors.discussion.lockedLabel);\n if (context.locked) {\n icon.removeClass('hidden');\n lockedLabel.removeAttr('hidden');\n } else {\n icon.addClass('hidden');\n lockedLabel.attr('hidden', true);\n }\n return context;\n })\n .then(function(context) {\n context.forumid = forumId;\n return Templates.render('mod_forum/discussion_lock_toggle', context);\n })\n .then(function(html, js) {\n return Templates.replaceNode(toggleElement, html, js);\n })\n .then(function() {\n return Str.get_string('lockupdated', 'forum')\n .done(function(s) {\n return Notification.addNotification({\n message: s,\n type: \"info\"\n });\n });\n })\n .catch(Notification.exception);\n\n e.preventDefault();\n });\n };\n\n return {\n init: function(root) {\n SubscriptionToggle.init(root, false, function(toggleElement, context) {\n var toggleId = toggleElement.attr('id');\n var newTargetState = context.userstate.subscribed ? 0 : 1;\n toggleElement.data('targetstate', newTargetState);\n\n var stringKey = context.userstate.subscribed ? 'unsubscribediscussion' : 'subscribediscussion';\n return Str.get_string(stringKey, 'mod_forum')\n .then(function(string) {\n toggleElement.closest('td').find('label[for=\"' + toggleId + '\"]').find('span').text(string);\n return string;\n });\n });\n registerEventListeners(root);\n }\n };\n});\n"],"names":["define","$","Templates","Str","Notification","SubscriptionToggle","Selectors","Repository","PubSub","ForumEvents","FormChangeChecker","init","root","toggleElement","context","toggleId","attr","newTargetState","userstate","subscribed","data","stringKey","get_string","then","string","closest","find","text","subscribe","SUBSCRIPTION_TOGGLED","discussionId","subscriptionState","discussionListItem","discussion","item","subscribedLabel","addClass","removeAttr","removeClass","on","post","inpageCancelButton","e","resetFormDirtyState","currentTarget","favourite","toggle","preventDefault","this","forumId","setFavouriteDiscussionState","location","reload","catch","exception","pin","state","setPinDiscussionState","lock","setDiscussionLockState","icon","parents","summary","actions","lockedLabel","locked","forumid","render","html","js","replaceNode","done","s","addNotification","message","type","registerEventListeners"],"mappings":"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"} \ No newline at end of file diff --git a/mod/forum/amd/build/inpage_reply.min.js b/mod/forum/amd/build/inpage_reply.min.js index cce030ebc45..8421bdfff55 100644 --- a/mod/forum/amd/build/inpage_reply.min.js +++ b/mod/forum/amd/build/inpage_reply.min.js @@ -5,6 +5,6 @@ * @copyright 2019 Peter Dias * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("mod_forum/inpage_reply",["jquery","core/templates","core/notification","mod_forum/repository","mod_forum/selectors","core_form/changechecker"],(function($,Templates,Notification,Repository,Selectors,FormChangeChecker){var DISPLAYCONSTANTS_NESTED_V2=4,DISPLAYCONSTANTS_THREADED=2,DISPLAYCONSTANTS_NESTED=3,DISPLAYCONSTANTS_FLAT_NEWEST_FIRST=-1,EVENTS={POST_CREATED:"mod_forum-post-created"},CONTENT_FORMATS={MOODLE:0},hideSubmitButtonLoadingIcon=function(button){var textContainer=button.find(Selectors.post.inpageSubmitBtnText),loadingIconContainer=button.find(Selectors.post.loadingIconContainer);button.css("width",""),textContainer.removeClass("hidden"),loadingIconContainer.addClass("hidden")},registerEventListeners=function(root){root.on("click",Selectors.post.inpageSubmitBtn,(function(e){e.preventDefault();var newid,button,textContainer,loadingIconContainer,width,submitButton=$(e.currentTarget),allButtons=submitButton.parent().find(Selectors.post.inpageReplyButton),form=submitButton.parents(Selectors.post.inpageReplyForm).get(0),message=form.elements.post.value.trim(),messageformat=CONTENT_FORMATS.MOODLE,postid=form.elements.reply.value,subject=form.elements.subject.value,currentRoot=submitButton.closest(Selectors.post.post),isprivatereply=null!=form.elements.privatereply&&form.elements.privatereply.checked,modeSelector=root.find(Selectors.post.modeSelect),mode=modeSelector.length?parseInt(modeSelector.get(0).value):null;message.length&&(textContainer=(button=submitButton).find(Selectors.post.inpageSubmitBtnText),loadingIconContainer=button.find(Selectors.post.loadingIconContainer),width=button.outerWidth(),button.css("width",width),textContainer.addClass("hidden"),loadingIconContainer.removeClass("hidden"),allButtons.prop("disabled",!0),Repository.addDiscussionPost(postid,subject,message,messageformat,isprivatereply,!0).then((function(context){var message=context.messages.reduce((function(carry,message){return"success"==message.type&&(carry+="

"+message.message+"

"),carry}),"");return Notification.addNotification({message:message,type:"success"}),context})).then((function(context){form.reset();var post=context.post;switch(newid=post.id,mode){case DISPLAYCONSTANTS_NESTED_V2:var capabilities=post.capabilities,currentAuthorName=currentRoot.children().not(Selectors.post.repliesContainer).find(Selectors.post.authorName).text();return post.parentauthorname=currentAuthorName,post.showactionmenu=capabilities.view||capabilities.controlreadstatus||capabilities.edit||capabilities.split||capabilities.delete||capabilities.export||post.urls.viewparent,Templates.render("mod_forum/forum_discussion_nested_v2_post_reply",post);case DISPLAYCONSTANTS_THREADED:return Templates.render("mod_forum/forum_discussion_threaded_post",post);case DISPLAYCONSTANTS_NESTED:return Templates.render("mod_forum/forum_discussion_nested_post",post);default:return Templates.render("mod_forum/forum_discussion_post",post)}})).then((function(html,js){var repliesnode=currentRoot.find(Selectors.post.repliesContainer).first();return mode==DISPLAYCONSTANTS_FLAT_NEWEST_FIRST?Templates.prependNodeContents(repliesnode,html,js):Templates.appendNodeContents(repliesnode,html,js)})).then((function(){return submitButton.trigger(EVENTS.POST_CREATED,newid),hideSubmitButtonLoadingIcon(submitButton),allButtons.prop("disabled",!1),FormChangeChecker.resetFormDirtyState(submitButton[0]),currentRoot.find(Selectors.post.inpageReplyContent).hide()})).then((function(){location.href="#p"+newid,location.reload()})).catch((function(error){return hideSubmitButtonLoadingIcon(submitButton),allButtons.prop("disabled",!1),Notification.exception(error)})))})),root.on("click",Selectors.post.inpageCancelButton,(function(){void 0!==M.core_formchangechecker&&M.core_formchangechecker.reset_form_dirty_state()}))};return{init:function(root){registerEventListeners(root)},CONTENT_FORMATS:CONTENT_FORMATS,EVENTS:EVENTS}})); +define("mod_forum/inpage_reply",["jquery","core/templates","core/notification","mod_forum/repository","mod_forum/selectors","core_form/changechecker"],(function($,Templates,Notification,Repository,Selectors,FormChangeChecker){var DISPLAYCONSTANTS_NESTED_V2=4,DISPLAYCONSTANTS_THREADED=2,DISPLAYCONSTANTS_NESTED=3,DISPLAYCONSTANTS_FLAT_NEWEST_FIRST=-1,EVENTS={POST_CREATED:"mod_forum-post-created"},CONTENT_FORMATS={MOODLE:0},hideSubmitButtonLoadingIcon=function(button){var textContainer=button.find(Selectors.post.inpageSubmitBtnText),loadingIconContainer=button.find(Selectors.post.loadingIconContainer);button.css("width",""),textContainer.removeClass("hidden"),loadingIconContainer.addClass("hidden")},registerEventListeners=function(root){root.on("click",Selectors.post.inpageSubmitBtn,(function(e){e.preventDefault();var newid,button,textContainer,loadingIconContainer,width,submitButton=$(e.currentTarget),allButtons=submitButton.parent().find(Selectors.post.inpageReplyButton),form=submitButton.parents(Selectors.post.inpageReplyForm).get(0),message=form.elements.post.value.trim(),messageformat=CONTENT_FORMATS.MOODLE,postid=form.elements.reply.value,subject=form.elements.subject.value,currentRoot=submitButton.closest(Selectors.post.post),isprivatereply=null!=form.elements.privatereply&&form.elements.privatereply.checked,modeSelector=root.find(Selectors.post.modeSelect),mode=modeSelector.length?parseInt(modeSelector.get(0).value):null;message.length&&(textContainer=(button=submitButton).find(Selectors.post.inpageSubmitBtnText),loadingIconContainer=button.find(Selectors.post.loadingIconContainer),width=button.outerWidth(),button.css("width",width),textContainer.addClass("hidden"),loadingIconContainer.removeClass("hidden"),allButtons.prop("disabled",!0),Repository.addDiscussionPost(postid,subject,message,messageformat,isprivatereply,!0).then((function(context){var message=context.messages.reduce((function(carry,message){return"success"==message.type&&(carry+="

"+message.message+"

"),carry}),"");return Notification.addNotification({message:message,type:"success"}),context})).then((function(context){form.reset();var post=context.post;switch(newid=post.id,mode){case DISPLAYCONSTANTS_NESTED_V2:var capabilities=post.capabilities,currentAuthorName=currentRoot.children().not(Selectors.post.repliesContainer).find(Selectors.post.authorName).text();return post.parentauthorname=currentAuthorName,post.showactionmenu=capabilities.view||capabilities.controlreadstatus||capabilities.edit||capabilities.split||capabilities.delete||capabilities.export||post.urls.viewparent,Templates.render("mod_forum/forum_discussion_nested_v2_post_reply",post);case DISPLAYCONSTANTS_THREADED:return Templates.render("mod_forum/forum_discussion_threaded_post",post);case DISPLAYCONSTANTS_NESTED:return Templates.render("mod_forum/forum_discussion_nested_post",post);default:return Templates.render("mod_forum/forum_discussion_post",post)}})).then((function(html,js){var repliesnode=currentRoot.find(Selectors.post.repliesContainer).first();return mode==DISPLAYCONSTANTS_FLAT_NEWEST_FIRST?Templates.prependNodeContents(repliesnode,html,js):Templates.appendNodeContents(repliesnode,html,js)})).then((function(){return submitButton.trigger(EVENTS.POST_CREATED,newid),hideSubmitButtonLoadingIcon(submitButton),allButtons.prop("disabled",!1),FormChangeChecker.resetFormDirtyState(submitButton[0]),currentRoot.find(Selectors.post.inpageReplyContent).hide()})).then((function(){location.href="#p"+newid,location.reload()})).catch((function(error){return hideSubmitButtonLoadingIcon(submitButton),allButtons.prop("disabled",!1),Notification.exception(error)})))})),root.on("click",Selectors.post.inpageCancelButton,(function(e){FormChangeChecker.resetFormDirtyState(e.currentTarget)}))};return{init:function(root){registerEventListeners(root)},CONTENT_FORMATS:CONTENT_FORMATS,EVENTS:EVENTS}})); //# sourceMappingURL=inpage_reply.min.js.map \ No newline at end of file diff --git a/mod/forum/amd/build/inpage_reply.min.js.map b/mod/forum/amd/build/inpage_reply.min.js.map index 727649e48e8..679a7753041 100644 --- a/mod/forum/amd/build/inpage_reply.min.js.map +++ b/mod/forum/amd/build/inpage_reply.min.js.map @@ -1 +1 @@ -{"version":3,"file":"inpage_reply.min.js","sources":["../src/inpage_reply.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * This module handles the in page replying to forum posts.\n *\n * @module mod_forum/inpage_reply\n * @copyright 2019 Peter Dias\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 'mod_forum/repository',\n 'mod_forum/selectors',\n 'core_form/changechecker',\n], function(\n $,\n Templates,\n Notification,\n Repository,\n Selectors,\n FormChangeChecker\n) {\n\n var DISPLAYCONSTANTS = {\n NESTED_V2: 4,\n THREADED: 2,\n NESTED: 3,\n FLAT_OLDEST_FIRST: 1,\n FLAT_NEWEST_FIRST: -1\n };\n\n var EVENTS = {\n POST_CREATED: 'mod_forum-post-created'\n };\n\n /**\n * Moodle formats taken from the FORMAT_* constants declared in lib/weblib.php.\n * @type {Object}\n */\n var CONTENT_FORMATS = {\n MOODLE: 0\n };\n /**\n * Show the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var showSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n var width = button.outerWidth();\n // Fix the width so that the button size doesn't change when we show the loading icon.\n button.css('width', width);\n textContainer.addClass('hidden');\n loadingIconContainer.removeClass('hidden');\n };\n\n /**\n * Hide the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var hideSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n // Reset the width back to it's default.\n button.css('width', '');\n textContainer.removeClass('hidden');\n loadingIconContainer.addClass('hidden');\n };\n\n /**\n * Register the event listeners for the submit/cancel buttons of the in page reply.\n *\n * @param {Object} root The discussion container element.\n */\n var registerEventListeners = function(root) {\n root.on('click', Selectors.post.inpageSubmitBtn, function(e) {\n e.preventDefault();\n var submitButton = $(e.currentTarget);\n var allButtons = submitButton.parent().find(Selectors.post.inpageReplyButton);\n var form = submitButton.parents(Selectors.post.inpageReplyForm).get(0);\n var message = form.elements.post.value.trim();\n // For now, we consider the inline reply post written using the FORMAT_MOODLE (because a textarea is displayed).\n // In the future, other formats should be supported, letting users to use their preferred editor and format.\n var messageformat = CONTENT_FORMATS.MOODLE;\n // The message post will be converted from messageformat to FORMAT_HTML.\n var topreferredformat = true;\n var postid = form.elements.reply.value;\n var subject = form.elements.subject.value;\n var currentRoot = submitButton.closest(Selectors.post.post);\n var isprivatereply = form.elements.privatereply != undefined ? form.elements.privatereply.checked : false;\n var modeSelector = root.find(Selectors.post.modeSelect);\n var mode = modeSelector.length ? parseInt(modeSelector.get(0).value) : null;\n var newid;\n\n if (message.length) {\n showSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', true);\n\n Repository.addDiscussionPost(postid, subject, message, messageformat, isprivatereply, topreferredformat)\n .then(function(context) {\n var message = context.messages.reduce(function(carry, message) {\n if (message.type == 'success') {\n carry += '

' + message.message + '

';\n }\n return carry;\n }, '');\n Notification.addNotification({\n message: message,\n type: \"success\"\n });\n\n return context;\n })\n .then(function(context) {\n form.reset();\n var post = context.post;\n newid = post.id;\n\n switch (mode) {\n case DISPLAYCONSTANTS.NESTED_V2:\n var capabilities = post.capabilities;\n var currentAuthorName = currentRoot.children()\n .not(Selectors.post.repliesContainer)\n .find(Selectors.post.authorName)\n .text();\n post.parentauthorname = currentAuthorName;\n post.showactionmenu = capabilities.view ||\n capabilities.controlreadstatus ||\n capabilities.edit ||\n capabilities.split ||\n capabilities.delete ||\n capabilities.export ||\n post.urls.viewparent;\n return Templates.render('mod_forum/forum_discussion_nested_v2_post_reply', post);\n case DISPLAYCONSTANTS.THREADED:\n return Templates.render('mod_forum/forum_discussion_threaded_post', post);\n case DISPLAYCONSTANTS.NESTED:\n return Templates.render('mod_forum/forum_discussion_nested_post', post);\n default:\n return Templates.render('mod_forum/forum_discussion_post', post);\n }\n })\n .then(function(html, js) {\n var repliesnode = currentRoot.find(Selectors.post.repliesContainer).first();\n\n if (mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) {\n return Templates.prependNodeContents(repliesnode, html, js);\n } else {\n return Templates.appendNodeContents(repliesnode, html, js);\n }\n })\n .then(function() {\n submitButton.trigger(EVENTS.POST_CREATED, newid);\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n\n // Tell formchangechecker we submitted the form.\n FormChangeChecker.resetFormDirtyState(submitButton[0]);\n\n return currentRoot.find(Selectors.post.inpageReplyContent).hide();\n })\n .then(function() {\n location.href = \"#p\" + newid;\n\n // Reload the page, say if threshold is being set by user those would get reflected through the templates.\n location.reload();\n })\n .catch(function(error) {\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n return Notification.exception(error);\n });\n }\n });\n\n root.on('click', Selectors.post.inpageCancelButton, function() {\n // Tell formchangechecker to reset the form state.\n if (typeof M.core_formchangechecker !== 'undefined') {\n M.core_formchangechecker.reset_form_dirty_state();\n }\n });\n };\n\n return {\n init: function(root) {\n registerEventListeners(root);\n },\n CONTENT_FORMATS: CONTENT_FORMATS,\n EVENTS: EVENTS\n };\n});\n"],"names":["define","$","Templates","Notification","Repository","Selectors","FormChangeChecker","DISPLAYCONSTANTS","EVENTS","POST_CREATED","CONTENT_FORMATS","MOODLE","hideSubmitButtonLoadingIcon","button","textContainer","find","post","inpageSubmitBtnText","loadingIconContainer","css","removeClass","addClass","registerEventListeners","root","on","inpageSubmitBtn","e","preventDefault","newid","width","submitButton","currentTarget","allButtons","parent","inpageReplyButton","form","parents","inpageReplyForm","get","message","elements","value","trim","messageformat","postid","reply","subject","currentRoot","closest","isprivatereply","undefined","privatereply","checked","modeSelector","modeSelect","mode","length","parseInt","outerWidth","prop","addDiscussionPost","then","context","messages","reduce","carry","type","addNotification","reset","id","capabilities","currentAuthorName","children","not","repliesContainer","authorName","text","parentauthorname","showactionmenu","view","controlreadstatus","edit","split","delete","export","urls","viewparent","render","html","js","repliesnode","first","prependNodeContents","appendNodeContents","trigger","resetFormDirtyState","inpageReplyContent","hide","location","href","reload","catch","error","exception","inpageCancelButton","M","core_formchangechecker","reset_form_dirty_state","init"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"inpage_reply.min.js","sources":["../src/inpage_reply.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * This module handles the in page replying to forum posts.\n *\n * @module mod_forum/inpage_reply\n * @copyright 2019 Peter Dias\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 'mod_forum/repository',\n 'mod_forum/selectors',\n 'core_form/changechecker',\n], function(\n $,\n Templates,\n Notification,\n Repository,\n Selectors,\n FormChangeChecker\n) {\n\n var DISPLAYCONSTANTS = {\n NESTED_V2: 4,\n THREADED: 2,\n NESTED: 3,\n FLAT_OLDEST_FIRST: 1,\n FLAT_NEWEST_FIRST: -1\n };\n\n var EVENTS = {\n POST_CREATED: 'mod_forum-post-created'\n };\n\n /**\n * Moodle formats taken from the FORMAT_* constants declared in lib/weblib.php.\n * @type {Object}\n */\n var CONTENT_FORMATS = {\n MOODLE: 0\n };\n /**\n * Show the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var showSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n var width = button.outerWidth();\n // Fix the width so that the button size doesn't change when we show the loading icon.\n button.css('width', width);\n textContainer.addClass('hidden');\n loadingIconContainer.removeClass('hidden');\n };\n\n /**\n * Hide the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var hideSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n // Reset the width back to it's default.\n button.css('width', '');\n textContainer.removeClass('hidden');\n loadingIconContainer.addClass('hidden');\n };\n\n /**\n * Register the event listeners for the submit/cancel buttons of the in page reply.\n *\n * @param {Object} root The discussion container element.\n */\n var registerEventListeners = function(root) {\n root.on('click', Selectors.post.inpageSubmitBtn, function(e) {\n e.preventDefault();\n var submitButton = $(e.currentTarget);\n var allButtons = submitButton.parent().find(Selectors.post.inpageReplyButton);\n var form = submitButton.parents(Selectors.post.inpageReplyForm).get(0);\n var message = form.elements.post.value.trim();\n // For now, we consider the inline reply post written using the FORMAT_MOODLE (because a textarea is displayed).\n // In the future, other formats should be supported, letting users to use their preferred editor and format.\n var messageformat = CONTENT_FORMATS.MOODLE;\n // The message post will be converted from messageformat to FORMAT_HTML.\n var topreferredformat = true;\n var postid = form.elements.reply.value;\n var subject = form.elements.subject.value;\n var currentRoot = submitButton.closest(Selectors.post.post);\n var isprivatereply = form.elements.privatereply != undefined ? form.elements.privatereply.checked : false;\n var modeSelector = root.find(Selectors.post.modeSelect);\n var mode = modeSelector.length ? parseInt(modeSelector.get(0).value) : null;\n var newid;\n\n if (message.length) {\n showSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', true);\n\n Repository.addDiscussionPost(postid, subject, message, messageformat, isprivatereply, topreferredformat)\n .then(function(context) {\n var message = context.messages.reduce(function(carry, message) {\n if (message.type == 'success') {\n carry += '

' + message.message + '

';\n }\n return carry;\n }, '');\n Notification.addNotification({\n message: message,\n type: \"success\"\n });\n\n return context;\n })\n .then(function(context) {\n form.reset();\n var post = context.post;\n newid = post.id;\n\n switch (mode) {\n case DISPLAYCONSTANTS.NESTED_V2:\n var capabilities = post.capabilities;\n var currentAuthorName = currentRoot.children()\n .not(Selectors.post.repliesContainer)\n .find(Selectors.post.authorName)\n .text();\n post.parentauthorname = currentAuthorName;\n post.showactionmenu = capabilities.view ||\n capabilities.controlreadstatus ||\n capabilities.edit ||\n capabilities.split ||\n capabilities.delete ||\n capabilities.export ||\n post.urls.viewparent;\n return Templates.render('mod_forum/forum_discussion_nested_v2_post_reply', post);\n case DISPLAYCONSTANTS.THREADED:\n return Templates.render('mod_forum/forum_discussion_threaded_post', post);\n case DISPLAYCONSTANTS.NESTED:\n return Templates.render('mod_forum/forum_discussion_nested_post', post);\n default:\n return Templates.render('mod_forum/forum_discussion_post', post);\n }\n })\n .then(function(html, js) {\n var repliesnode = currentRoot.find(Selectors.post.repliesContainer).first();\n\n if (mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) {\n return Templates.prependNodeContents(repliesnode, html, js);\n } else {\n return Templates.appendNodeContents(repliesnode, html, js);\n }\n })\n .then(function() {\n submitButton.trigger(EVENTS.POST_CREATED, newid);\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n\n // Tell formchangechecker we submitted the form.\n FormChangeChecker.resetFormDirtyState(submitButton[0]);\n\n return currentRoot.find(Selectors.post.inpageReplyContent).hide();\n })\n .then(function() {\n location.href = \"#p\" + newid;\n\n // Reload the page, say if threshold is being set by user those would get reflected through the templates.\n location.reload();\n })\n .catch(function(error) {\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n return Notification.exception(error);\n });\n }\n });\n\n root.on('click', Selectors.post.inpageCancelButton, function(e) {\n // Tell formchangechecker to reset the form state.\n FormChangeChecker.resetFormDirtyState(e.currentTarget);\n });\n };\n\n return {\n init: function(root) {\n registerEventListeners(root);\n },\n CONTENT_FORMATS: CONTENT_FORMATS,\n EVENTS: EVENTS\n };\n});\n"],"names":["define","$","Templates","Notification","Repository","Selectors","FormChangeChecker","DISPLAYCONSTANTS","EVENTS","POST_CREATED","CONTENT_FORMATS","MOODLE","hideSubmitButtonLoadingIcon","button","textContainer","find","post","inpageSubmitBtnText","loadingIconContainer","css","removeClass","addClass","registerEventListeners","root","on","inpageSubmitBtn","e","preventDefault","newid","width","submitButton","currentTarget","allButtons","parent","inpageReplyButton","form","parents","inpageReplyForm","get","message","elements","value","trim","messageformat","postid","reply","subject","currentRoot","closest","isprivatereply","undefined","privatereply","checked","modeSelector","modeSelect","mode","length","parseInt","outerWidth","prop","addDiscussionPost","then","context","messages","reduce","carry","type","addNotification","reset","id","capabilities","currentAuthorName","children","not","repliesContainer","authorName","text","parentauthorname","showactionmenu","view","controlreadstatus","edit","split","delete","export","urls","viewparent","render","html","js","repliesnode","first","prependNodeContents","appendNodeContents","trigger","resetFormDirtyState","inpageReplyContent","hide","location","href","reload","catch","error","exception","inpageCancelButton","init"],"mappings":"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"} \ No newline at end of file diff --git a/mod/forum/amd/src/discussion_list.js b/mod/forum/amd/src/discussion_list.js index 2f6f4f7734d..97bf7273373 100644 --- a/mod/forum/amd/src/discussion_list.js +++ b/mod/forum/amd/src/discussion_list.js @@ -30,6 +30,7 @@ define([ 'mod_forum/repository', 'core/pubsub', 'mod_forum/forum_events', + 'core_form/changechecker', ], function( $, Templates, @@ -39,7 +40,8 @@ define([ Selectors, Repository, PubSub, - ForumEvents + ForumEvents, + FormChangeChecker ) { var registerEventListeners = function(root) { PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED, function(data) { @@ -56,11 +58,9 @@ define([ } }); - root.on('click', Selectors.post.inpageCancelButton, function() { + root.on('click', Selectors.post.inpageCancelButton, function(e) { // Tell formchangechecker to reset the form state. - if (typeof M.core_formchangechecker !== 'undefined') { - M.core_formchangechecker.reset_form_dirty_state(); - } + FormChangeChecker.resetFormDirtyState(e.currentTarget); }); root.on('click', Selectors.favourite.toggle, function(e) { diff --git a/mod/forum/amd/src/inpage_reply.js b/mod/forum/amd/src/inpage_reply.js index 452b17169da..573201ffe1a 100644 --- a/mod/forum/amd/src/inpage_reply.js +++ b/mod/forum/amd/src/inpage_reply.js @@ -190,11 +190,9 @@ define([ } }); - root.on('click', Selectors.post.inpageCancelButton, function() { + root.on('click', Selectors.post.inpageCancelButton, function(e) { // Tell formchangechecker to reset the form state. - if (typeof M.core_formchangechecker !== 'undefined') { - M.core_formchangechecker.reset_form_dirty_state(); - } + FormChangeChecker.resetFormDirtyState(e.currentTarget); }); }; From e2cb2fa5dc0c896941e2815765a5f6835bad65a7 Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Wed, 20 Sep 2023 18:43:52 +0100 Subject: [PATCH 2/2] MDL-72308 forms: final removal of legacy formchangechecker YUI. --- .../moodle-editor_atto-editor-debug.js | 2 +- .../moodle-editor_atto-editor.js | 2 +- lib/editor/atto/yui/src/editor/js/textarea.js | 2 +- lib/form/amd/build/changechecker.min.js | 2 +- lib/form/amd/build/changechecker.min.js.map | 2 +- lib/form/amd/src/changechecker.js | 30 -------- lib/form/upgrade.txt | 2 + .../moodle-core-formchangechecker-debug.js | 73 ------------------- .../moodle-core-formchangechecker-min.js | 1 - .../moodle-core-formchangechecker.js | 73 ------------------- lib/yui/src/formchangechecker/build.json | 10 --- .../formchangechecker/js/formchangechecker.js | 68 ----------------- .../meta/formchangechecker.json | 9 --- 13 files changed, 7 insertions(+), 269 deletions(-) delete mode 100644 lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-debug.js delete mode 100644 lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-min.js delete mode 100644 lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker.js delete mode 100644 lib/yui/src/formchangechecker/build.json delete mode 100644 lib/yui/src/formchangechecker/js/formchangechecker.js delete mode 100644 lib/yui/src/formchangechecker/meta/formchangechecker.json diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js index a70b48b4a00..0021dde2476 100644 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js @@ -781,7 +781,7 @@ EditorTextArea.prototype = { // Insert the cleaned content. this.textarea.set('value', newValue); - // Trigger the onchange callback on the textarea, essentially to notify moodle-core-formchangechecker. + // Trigger the onchange callback on the textarea, essentially to notify the formchangechecker module. this.textarea.simulate('change'); // Trigger handlers for this action. diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js index 3d14624c149..482b0153ba8 100644 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js @@ -776,7 +776,7 @@ EditorTextArea.prototype = { // Insert the cleaned content. this.textarea.set('value', newValue); - // Trigger the onchange callback on the textarea, essentially to notify moodle-core-formchangechecker. + // Trigger the onchange callback on the textarea, essentially to notify the formchangechecker module. this.textarea.simulate('change'); // Trigger handlers for this action. diff --git a/lib/editor/atto/yui/src/editor/js/textarea.js b/lib/editor/atto/yui/src/editor/js/textarea.js index 3405590337a..4c75a434f17 100644 --- a/lib/editor/atto/yui/src/editor/js/textarea.js +++ b/lib/editor/atto/yui/src/editor/js/textarea.js @@ -106,7 +106,7 @@ EditorTextArea.prototype = { // Insert the cleaned content. this.textarea.set('value', newValue); - // Trigger the onchange callback on the textarea, essentially to notify moodle-core-formchangechecker. + // Trigger the onchange callback on the textarea, essentially to notify the formchangechecker module. this.textarea.simulate('change'); // Trigger handlers for this action. diff --git a/lib/form/amd/build/changechecker.min.js b/lib/form/amd/build/changechecker.min.js index eed0e56e234..f1eafc401e1 100644 --- a/lib/form/amd/build/changechecker.min.js +++ b/lib/form/amd/build/changechecker.min.js @@ -48,6 +48,6 @@ define("core_form/changechecker",["exports","core_editor/events","core/str"],(fu * }); * {{/js}} */ -let warningString,watchedForms=[],formChangeCheckerDisabled=!1;const getFormFromChild=formChild=>formChild.closest("form"),watchForm=formNode=>{(formNode=getFormFromChild(formNode))&&(isWatchingForm(formNode)||watchedForms.push(formNode))};_exports.watchForm=watchForm;_exports.unWatchForm=formNode=>{watchedForms=watchedForms.filter((watchedForm=>!!watchedForm.contains(formNode)))};const resetAllFormDirtyStates=()=>{watchedForms.forEach((watchedForm=>{watchedForm.dataset.formSubmitted="false",watchedForm.dataset.formDirty="false"}))};_exports.resetAllFormDirtyStates=resetAllFormDirtyStates;const resetFormDirtyState=formNode=>{(formNode=getFormFromChild(formNode))&&(formNode.dataset.formSubmitted="false",formNode.dataset.formDirty="false")};_exports.resetFormDirtyState=resetFormDirtyState;const markAllFormsAsDirty=()=>{watchedForms.forEach((watchedForm=>{watchedForm.dataset.formDirty="true"}))};_exports.markAllFormsAsDirty=markAllFormsAsDirty;const markFormAsDirty=formNode=>{(formNode=getFormFromChild(formNode))&&(formNode.dataset.formDirty="true")};_exports.markFormAsDirty=markFormAsDirty;const disableAllChecks=()=>{formChangeCheckerDisabled=!0};_exports.disableAllChecks=disableAllChecks;const isAnyWatchedFormDirty=()=>{if(formChangeCheckerDisabled)return!1;if(watchedForms.some((watchedForm=>"true"===watchedForm.dataset.formSubmitted)))return!1;return!!watchedForms.some((watchedForm=>{if(!watchedForm.isConnected)return!1;if("true"===watchedForm.dataset.formDirty)return!0;if(document.activeElement&&document.activeElement.dataset.propertyIsEnumerable("initialValue")){const isActiveElementWatched=isWatchingForm(document.activeElement)&&!shouldIgnoreChangesForNode(document.activeElement),hasValueChanged=document.activeElement.dataset.initialValue!==document.activeElement.value;if(isActiveElementWatched&&hasValueChanged)return!0}return!1}))||!(void 0===window.tinyMCE||!window.tinyMCE.editors||!window.tinyMCE.editors.some((editor=>editor.isDirty())))};_exports.isAnyWatchedFormDirty=isAnyWatchedFormDirty;const isWatchingForm=target=>watchedForms.some((watchedForm=>watchedForm.contains(target))),shouldIgnoreChangesForNode=target=>!!target.closest(".ignoredirty"),markFormChangedFromNode=changedNode=>{if(changedNode.dataset.formChangeCheckerOverride)return void disableAllChecks();if(!isWatchingForm(changedNode))return;if(shouldIgnoreChangesForNode(changedNode))return;var target;(target=changedNode,watchedForms.find((watchedForm=>watchedForm.contains(target)))).dataset.formDirty="true"};_exports.markFormChangedFromNode=markFormChangedFromNode;const markFormSubmitted=formNode=>{(formNode=getFormFromChild(formNode))&&(formNode.dataset.formSubmitted="true")};_exports.markFormSubmitted=markFormSubmitted;const markAllFormsSubmitted=()=>{watchedForms.forEach((watchedForm=>markFormSubmitted(watchedForm)))};_exports.markAllFormsSubmitted=markAllFormsSubmitted;const beforeUnloadHandler=e=>isAnyWatchedFormDirty()&&!M.cfg.behatsiterunning?(e.preventDefault(),e.returnValue=warningString,e.returnValue):(window.removeEventListener("beforeunload",beforeUnloadHandler),null),startWatching=()=>{addLegacyFunctions(),document.addEventListener("change",(e=>{isWatchingForm(e.target)&&markFormChangedFromNode(e.target)})),document.addEventListener("click",(e=>{if(!e.target.closest("[data-formchangechecker-ignore-submit]"))return;const ownerForm=getFormFromChild(e.target);ownerForm&&(ownerForm.dataset.ignoreSubmission="true")})),document.addEventListener("focusin",(e=>{if(e.target.matches("input, textarea, select")){if(e.target.dataset.propertyIsEnumerable("initialValue"))return;e.target.dataset.initialValue=e.target.value}})),document.addEventListener("submit",(e=>{const formNode=getFormFromChild(e.target);formNode&&(formNode.dataset.ignoreSubmission?formNode.dataset.ignoreSubmission="false":markFormSubmitted(formNode))})),document.addEventListener(_events.eventTypes.editorContentRestored,(e=>{e.target!=document?resetFormDirtyState(e.target):resetAllFormDirtyStates()})),(0,_str.getString)("changesmadereallygoaway","moodle").then((changesMadeString=>{warningString=changesMadeString})).catch(),window.addEventListener("beforeunload",beforeUnloadHandler)};_exports.startWatching=startWatching;const addLegacyFunctions=()=>{const getLoggedLegacyFallback=(oldFunctionName,newFunctionName,newFunction)=>function(){window.console.warn("The moodle-core-formchangechecker has been deprecated and replaced with core_form/changechecker. "+"The ".concat(oldFunctionName," function has been replaced with ").concat(newFunctionName,".")),newFunction(...arguments)};window.M.core_formchangechecker={init:getLoggedLegacyFallback("init","watchFormById",watchFormById),reset_form_dirty_state:getLoggedLegacyFallback("reset_form_dirty_state","resetFormDirtyState",resetAllFormDirtyStates),set_form_changed:getLoggedLegacyFallback("set_form_changed","markFormAsDirty",markAllFormsAsDirty),set_form_submitted:getLoggedLegacyFallback("set_form_submitted","markFormSubmitted",markAllFormsSubmitted)}},watchFormById=formId=>{watchForm(document.getElementById(formId))};_exports.watchFormById=watchFormById;_exports.resetFormDirtyStateById=formId=>{resetFormDirtyState(document.getElementById(formId))};_exports.markFormAsDirtyById=formId=>{markFormAsDirty(document.getElementById(formId))},startWatching()})); +let warningString,watchedForms=[],formChangeCheckerDisabled=!1;const getFormFromChild=formChild=>formChild.closest("form"),watchForm=formNode=>{(formNode=getFormFromChild(formNode))&&(isWatchingForm(formNode)||watchedForms.push(formNode))};_exports.watchForm=watchForm;_exports.unWatchForm=formNode=>{watchedForms=watchedForms.filter((watchedForm=>!!watchedForm.contains(formNode)))};const resetAllFormDirtyStates=()=>{watchedForms.forEach((watchedForm=>{watchedForm.dataset.formSubmitted="false",watchedForm.dataset.formDirty="false"}))};_exports.resetAllFormDirtyStates=resetAllFormDirtyStates;const resetFormDirtyState=formNode=>{(formNode=getFormFromChild(formNode))&&(formNode.dataset.formSubmitted="false",formNode.dataset.formDirty="false")};_exports.resetFormDirtyState=resetFormDirtyState;_exports.markAllFormsAsDirty=()=>{watchedForms.forEach((watchedForm=>{watchedForm.dataset.formDirty="true"}))};const markFormAsDirty=formNode=>{(formNode=getFormFromChild(formNode))&&(formNode.dataset.formDirty="true")};_exports.markFormAsDirty=markFormAsDirty;const disableAllChecks=()=>{formChangeCheckerDisabled=!0};_exports.disableAllChecks=disableAllChecks;const isAnyWatchedFormDirty=()=>{if(formChangeCheckerDisabled)return!1;if(watchedForms.some((watchedForm=>"true"===watchedForm.dataset.formSubmitted)))return!1;return!!watchedForms.some((watchedForm=>{if(!watchedForm.isConnected)return!1;if("true"===watchedForm.dataset.formDirty)return!0;if(document.activeElement&&document.activeElement.dataset.propertyIsEnumerable("initialValue")){const isActiveElementWatched=isWatchingForm(document.activeElement)&&!shouldIgnoreChangesForNode(document.activeElement),hasValueChanged=document.activeElement.dataset.initialValue!==document.activeElement.value;if(isActiveElementWatched&&hasValueChanged)return!0}return!1}))||!(void 0===window.tinyMCE||!window.tinyMCE.editors||!window.tinyMCE.editors.some((editor=>editor.isDirty())))};_exports.isAnyWatchedFormDirty=isAnyWatchedFormDirty;const isWatchingForm=target=>watchedForms.some((watchedForm=>watchedForm.contains(target))),shouldIgnoreChangesForNode=target=>!!target.closest(".ignoredirty"),markFormChangedFromNode=changedNode=>{if(changedNode.dataset.formChangeCheckerOverride)return void disableAllChecks();if(!isWatchingForm(changedNode))return;if(shouldIgnoreChangesForNode(changedNode))return;var target;(target=changedNode,watchedForms.find((watchedForm=>watchedForm.contains(target)))).dataset.formDirty="true"};_exports.markFormChangedFromNode=markFormChangedFromNode;const markFormSubmitted=formNode=>{(formNode=getFormFromChild(formNode))&&(formNode.dataset.formSubmitted="true")};_exports.markFormSubmitted=markFormSubmitted;_exports.markAllFormsSubmitted=()=>{watchedForms.forEach((watchedForm=>markFormSubmitted(watchedForm)))};const beforeUnloadHandler=e=>isAnyWatchedFormDirty()&&!M.cfg.behatsiterunning?(e.preventDefault(),e.returnValue=warningString,e.returnValue):(window.removeEventListener("beforeunload",beforeUnloadHandler),null),startWatching=()=>{document.addEventListener("change",(e=>{isWatchingForm(e.target)&&markFormChangedFromNode(e.target)})),document.addEventListener("click",(e=>{if(!e.target.closest("[data-formchangechecker-ignore-submit]"))return;const ownerForm=getFormFromChild(e.target);ownerForm&&(ownerForm.dataset.ignoreSubmission="true")})),document.addEventListener("focusin",(e=>{if(e.target.matches("input, textarea, select")){if(e.target.dataset.propertyIsEnumerable("initialValue"))return;e.target.dataset.initialValue=e.target.value}})),document.addEventListener("submit",(e=>{const formNode=getFormFromChild(e.target);formNode&&(formNode.dataset.ignoreSubmission?formNode.dataset.ignoreSubmission="false":markFormSubmitted(formNode))})),document.addEventListener(_events.eventTypes.editorContentRestored,(e=>{e.target!=document?resetFormDirtyState(e.target):resetAllFormDirtyStates()})),(0,_str.getString)("changesmadereallygoaway","moodle").then((changesMadeString=>{warningString=changesMadeString})).catch(),window.addEventListener("beforeunload",beforeUnloadHandler)};_exports.startWatching=startWatching;_exports.watchFormById=formId=>{watchForm(document.getElementById(formId))};_exports.resetFormDirtyStateById=formId=>{resetFormDirtyState(document.getElementById(formId))};_exports.markFormAsDirtyById=formId=>{markFormAsDirty(document.getElementById(formId))},startWatching()})); //# sourceMappingURL=changechecker.min.js.map \ No newline at end of file diff --git a/lib/form/amd/build/changechecker.min.js.map b/lib/form/amd/build/changechecker.min.js.map index 346588b4143..ffc4235ee58 100644 --- a/lib/form/amd/build/changechecker.min.js.map +++ b/lib/form/amd/build/changechecker.min.js.map @@ -1 +1 @@ -{"version":3,"file":"changechecker.min.js","sources":["../src/changechecker.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * This module provides change detection to forms, allowing a browser to warn the user before navigating away if changes\n * have been made.\n *\n * Two flags are stored for each form:\n * * a 'dirty' flag; and\n * * a 'submitted' flag.\n *\n * When the page is unloaded each watched form is checked. If the 'dirty' flag is set for any form, and the 'submitted'\n * flag is not set for any form, then a warning is shown.\n *\n * The 'dirty' flag is set when any form element is modified within a watched form.\n * The flag can also be set programatically. This may be required for custom form elements.\n *\n * It is not possible to customise the warning message in any modern browser.\n *\n * Please note that some browsers have controls on when these alerts may or may not be shown.\n * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload} for browser-specific\n * notes and references.\n *\n * @module core_form/changechecker\n * @copyright 2021 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @example Usage where the FormElement is already held\n *\n * import {watchForm} from 'core_form/changechecker';\n *\n * // Fetch the form element somehow.\n * watchForm(formElement);\n *\n * @example Usage from the child of a form - i.e. an input, button, div, etc.\n *\n * import {watchForm} from 'core_form/changechecker';\n *\n * // Watch the form by using a child of it.\n * watchForm(document.querySelector('input[data-foo=\"bar\"]'););\n *\n * @example Usage from within a template\n *
\n * \n *
\n * {{#js}}\n * require(['core_form/changechecker'], function(changeChecker) {\n * watchFormById('mod_example-entry-{{uniqid}}');\n * });\n * {{/js}}\n */\n\nimport {eventTypes} from 'core_editor/events';\nimport {getString} from 'core/str';\n\n/**\n * @property {Bool} initialised Whether the change checker has been initialised\n * @private\n */\nlet initialised = false;\n\n/**\n * @property {String} warningString The warning string to show on form change failure\n * @private\n */\nlet warningString;\n\n/**\n * @property {Array} watchedForms The list of watched forms\n * @private\n */\nlet watchedForms = [];\n\n/**\n * @property {Bool} formChangeCheckerDisabled Whether the form change checker has been actively disabled\n * @private\n */\nlet formChangeCheckerDisabled = false;\n\n/**\n * Get the nearest form element from a child element.\n *\n * @param {HTMLElement} formChild\n * @returns {HTMLFormElement|null}\n * @private\n */\nconst getFormFromChild = formChild => formChild.closest('form');\n\n/**\n * Watch the specified form for changes.\n *\n * @method\n * @param {HTMLElement} formNode\n */\nexport const watchForm = formNode => {\n // Normalise the formNode.\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n // No form found.\n return;\n }\n\n if (isWatchingForm(formNode)) {\n // This form is already watched.\n return;\n }\n\n watchedForms.push(formNode);\n};\n\n/**\n * Stop watching the specified form for changes.\n *\n * If the form was not watched, then no change is made.\n *\n * A child of the form may be passed instead.\n *\n * @method\n * @param {HTMLElement} formNode\n * @example Stop watching a form for changes\n * import {unWatchForm} from 'core_form/changechecker';\n *\n * // ...\n * document.addEventListener('click', e => {\n * if (e.target.closest('[data-action=\"changePage\"]')) {\n * unWatchForm(e.target);\n * }\n * });\n */\nexport const unWatchForm = formNode => {\n watchedForms = watchedForms.filter(watchedForm => !!watchedForm.contains(formNode));\n};\n\n/**\n * Reset the 'dirty' flag for all watched forms.\n *\n * If a form was previously marked as 'dirty', then this flag will be cleared and when the page is unloaded no warning\n * will be shown.\n *\n * @method\n */\nexport const resetAllFormDirtyStates = () => {\n watchedForms.forEach(watchedForm => {\n watchedForm.dataset.formSubmitted = \"false\";\n watchedForm.dataset.formDirty = \"false\";\n });\n};\n\n/**\n * Reset the 'dirty' flag of the specified form.\n *\n * @method\n * @param {HTMLElement} formNode\n */\nexport const resetFormDirtyState = formNode => {\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n return;\n }\n\n formNode.dataset.formSubmitted = \"false\";\n formNode.dataset.formDirty = \"false\";\n};\n\n/**\n * Mark all forms as dirty.\n *\n * This function is only for backwards-compliance with the old YUI module and should not be used in any other situation.\n * It will be removed in Moodle 4.4.\n *\n * @method\n */\nexport const markAllFormsAsDirty = () => {\n watchedForms.forEach(watchedForm => {\n watchedForm.dataset.formDirty = \"true\";\n });\n};\n\n/**\n * Mark a specific form as dirty.\n *\n * This behaviour may be required for custom form elements which are not caught by the standard change listeners.\n *\n * @method\n * @param {HTMLElement} formNode\n */\nexport const markFormAsDirty = formNode => {\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n return;\n }\n\n // Mark it as dirty.\n formNode.dataset.formDirty = \"true\";\n};\n\n/**\n * Actively disable the form change checker.\n *\n * Please note that it cannot be re-enabled once disabled.\n *\n * @method\n */\nexport const disableAllChecks = () => {\n formChangeCheckerDisabled = true;\n};\n\n/**\n * Check whether any watched from is dirty.\n *\n * @method\n * @returns {Bool}\n */\nexport const isAnyWatchedFormDirty = () => {\n if (formChangeCheckerDisabled) {\n // The form change checker is disabled.\n return false;\n }\n\n const hasSubmittedForm = watchedForms.some(watchedForm => watchedForm.dataset.formSubmitted === \"true\");\n if (hasSubmittedForm) {\n // Do not warn about submitted forms, ever.\n return false;\n }\n\n const hasDirtyForm = watchedForms.some(watchedForm => {\n if (!watchedForm.isConnected) {\n // The watched form is not connected to the DOM.\n return false;\n }\n\n if (watchedForm.dataset.formDirty === \"true\") {\n // The form has been marked as dirty.\n return true;\n }\n\n // Elements currently holding focus will not have triggered change detection.\n // Check whether the value matches the original value upon form load.\n if (document.activeElement && document.activeElement.dataset.propertyIsEnumerable('initialValue')) {\n const isActiveElementWatched = isWatchingForm(document.activeElement)\n && !shouldIgnoreChangesForNode(document.activeElement);\n const hasValueChanged = document.activeElement.dataset.initialValue !== document.activeElement.value;\n\n if (isActiveElementWatched && hasValueChanged) {\n return true;\n }\n }\n\n return false;\n });\n\n if (hasDirtyForm) {\n // At least one form is dirty.\n return true;\n }\n\n // Handle TinyMCE editor instances.\n // TinyMCE forms may not have been initialised at the time that startWatching is called.\n // Check whether any tinyMCE editor is dirty.\n if (typeof window.tinyMCE !== 'undefined' && window.tinyMCE.editors) {\n if (window.tinyMCE.editors.some(editor => editor.isDirty())) {\n return true;\n }\n }\n\n // No dirty forms detected.\n return false;\n};\n\n/**\n * Get the watched form for the specified target.\n *\n * @method\n * @param {HTMLNode} target\n * @returns {HTMLFormElement}\n * @private\n */\nconst getFormForNode = target => watchedForms.find(watchedForm => watchedForm.contains(target));\n\n/**\n * Whether the specified target is a watched form.\n *\n * @method\n * @param {HTMLNode} target\n * @returns {Bool}\n * @private\n */\nconst isWatchingForm = target => watchedForms.some(watchedForm => watchedForm.contains(target));\n\n/**\n * Whether the specified target should ignore changes or not.\n *\n * @method\n * @param {HTMLNode} target\n * @returns {Bool}\n * @private\n */\nconst shouldIgnoreChangesForNode = target => !!target.closest('.ignoredirty');\n\n/**\n * Mark a form as changed.\n *\n * @method\n * @param {HTMLElement} changedNode An element in the form which was changed\n */\nexport const markFormChangedFromNode = changedNode => {\n if (changedNode.dataset.formChangeCheckerOverride) {\n // Changes to this form node disable the form change checker entirely.\n // This is intended for select fields which cause an immediate redirect.\n disableAllChecks();\n return;\n }\n\n if (!isWatchingForm(changedNode)) {\n return;\n }\n\n if (shouldIgnoreChangesForNode(changedNode)) {\n return;\n }\n\n // Mark the form as dirty.\n const formNode = getFormForNode(changedNode);\n formNode.dataset.formDirty = \"true\";\n};\n\n/**\n * Mark a form as submitted.\n *\n * @method\n * @param {HTMLElement} formNode An element in the form to mark as submitted\n */\nexport const markFormSubmitted = formNode => {\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n return;\n }\n\n formNode.dataset.formSubmitted = \"true\";\n};\n\n/**\n * Mark all forms as submitted.\n *\n * This function is only for backwards-compliance with the old YUI module and should not be used in any other situation.\n * It will be removed in Moodle 4.4.\n *\n * @method\n */\nexport const markAllFormsSubmitted = () => {\n watchedForms.forEach(watchedForm => markFormSubmitted(watchedForm));\n};\n\n/**\n * Handle the beforeunload event.\n *\n * @method\n * @param {Event} e\n * @returns {string|null}\n * @private\n */\nconst beforeUnloadHandler = e => {\n // Please note: The use of Promises in this function is forbidden.\n // This is an event handler and _cannot_ be asynchronous.\n let warnBeforeUnload = isAnyWatchedFormDirty() && !M.cfg.behatsiterunning;\n if (warnBeforeUnload) {\n // According to the specification, to show the confirmation dialog an event handler should call preventDefault()\n // on the event.\n e.preventDefault();\n\n // However note that not all browsers support this method, and some instead require the event handler to\n // implement one of two legacy methods:\n // * assigning a string to the event's returnValue property; and\n // * returning a string from the event handler.\n\n // Assigning a string to the event's returnValue property.\n e.returnValue = warningString;\n\n // Returning a string from the event handler.\n return e.returnValue;\n }\n\n // Attaching an event handler/listener to window or document's beforeunload event prevents browsers from using\n // in-memory page navigation caches, like Firefox's Back-Forward cache or WebKit's Page Cache.\n // Remove the handler.\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n\n return null;\n};\n\n/**\n * Start watching for form changes.\n *\n * This function is called on module load, and should not normally be called.\n *\n * @method\n * @protected\n */\nexport const startWatching = () => {\n if (initialised) {\n return;\n }\n\n // Add legacy support to provide b/c for the old YUI version.\n addLegacyFunctions();\n\n document.addEventListener('change', e => {\n if (!isWatchingForm(e.target)) {\n return;\n }\n\n markFormChangedFromNode(e.target);\n });\n\n document.addEventListener('click', e => {\n const ignoredButton = e.target.closest('[data-formchangechecker-ignore-submit]');\n if (!ignoredButton) {\n return;\n }\n\n const ownerForm = getFormFromChild(e.target);\n if (ownerForm) {\n ownerForm.dataset.ignoreSubmission = \"true\";\n }\n });\n\n document.addEventListener('focusin', e => {\n if (e.target.matches('input, textarea, select')) {\n if (e.target.dataset.propertyIsEnumerable('initialValue')) {\n // The initial value has already been set.\n return;\n }\n e.target.dataset.initialValue = e.target.value;\n }\n });\n\n document.addEventListener('submit', e => {\n const formNode = getFormFromChild(e.target);\n if (!formNode) {\n // Weird, but watch for this anyway.\n return;\n }\n\n if (formNode.dataset.ignoreSubmission) {\n // This form was submitted by a button which requested that the form checked should not mark it as submitted.\n formNode.dataset.ignoreSubmission = \"false\";\n return;\n }\n\n markFormSubmitted(formNode);\n });\n\n document.addEventListener(eventTypes.editorContentRestored, e => {\n if (e.target != document) {\n resetFormDirtyState(e.target);\n } else {\n resetAllFormDirtyStates();\n }\n });\n\n getString('changesmadereallygoaway', 'moodle')\n .then(changesMadeString => {\n warningString = changesMadeString;\n return;\n })\n .catch();\n\n window.addEventListener('beforeunload', beforeUnloadHandler);\n};\n\n/**\n * Add legacy functions for backwards compatability.\n *\n * @method\n * @private\n */\nconst addLegacyFunctions = () => {\n // Create a curried function to log use of the old function and provide detail on its replacement.\n const getLoggedLegacyFallback = (oldFunctionName, newFunctionName, newFunction) => (...args) => {\n window.console.warn(\n `The moodle-core-formchangechecker has been deprecated ` +\n `and replaced with core_form/changechecker. ` +\n `The ${oldFunctionName} function has been replaced with ${newFunctionName}.`\n );\n newFunction(...args);\n };\n\n /* eslint-disable */\n window.M.core_formchangechecker = {\n init: getLoggedLegacyFallback('init', 'watchFormById', watchFormById),\n reset_form_dirty_state: getLoggedLegacyFallback('reset_form_dirty_state', 'resetFormDirtyState', resetAllFormDirtyStates),\n set_form_changed: getLoggedLegacyFallback('set_form_changed', 'markFormAsDirty', markAllFormsAsDirty),\n set_form_submitted: getLoggedLegacyFallback('set_form_submitted', 'markFormSubmitted', markAllFormsSubmitted),\n };\n /* eslint-enable */\n};\n\n/**\n * Watch the form matching the specified ID for changes.\n *\n * @method\n * @param {String} formId\n */\nexport const watchFormById = formId => {\n watchForm(document.getElementById(formId));\n};\n\n/**\n * Reset the dirty state of the form matching the specified ID..\n *\n * @method\n * @param {String} formId\n */\nexport const resetFormDirtyStateById = formId => {\n resetFormDirtyState(document.getElementById(formId));\n};\n\n/**\n * Mark the form matching the specified ID as dirty.\n *\n * @method\n * @param {String} formId\n */\nexport const markFormAsDirtyById = formId => {\n markFormAsDirty(document.getElementById(formId));\n};\n\n// Configure all event listeners.\nstartWatching();\n"],"names":["warningString","watchedForms","formChangeCheckerDisabled","getFormFromChild","formChild","closest","watchForm","formNode","isWatchingForm","push","filter","watchedForm","contains","resetAllFormDirtyStates","forEach","dataset","formSubmitted","formDirty","resetFormDirtyState","markAllFormsAsDirty","markFormAsDirty","disableAllChecks","isAnyWatchedFormDirty","some","isConnected","document","activeElement","propertyIsEnumerable","isActiveElementWatched","shouldIgnoreChangesForNode","hasValueChanged","initialValue","value","window","tinyMCE","editors","editor","isDirty","target","markFormChangedFromNode","changedNode","formChangeCheckerOverride","find","markFormSubmitted","markAllFormsSubmitted","beforeUnloadHandler","e","M","cfg","behatsiterunning","preventDefault","returnValue","removeEventListener","startWatching","addLegacyFunctions","addEventListener","ownerForm","ignoreSubmission","matches","eventTypes","editorContentRestored","then","changesMadeString","catch","getLoggedLegacyFallback","oldFunctionName","newFunctionName","newFunction","console","warn","core_formchangechecker","init","watchFormById","reset_form_dirty_state","set_form_changed","set_form_submitted","formId","getElementById"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"changechecker.min.js","sources":["../src/changechecker.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * This module provides change detection to forms, allowing a browser to warn the user before navigating away if changes\n * have been made.\n *\n * Two flags are stored for each form:\n * * a 'dirty' flag; and\n * * a 'submitted' flag.\n *\n * When the page is unloaded each watched form is checked. If the 'dirty' flag is set for any form, and the 'submitted'\n * flag is not set for any form, then a warning is shown.\n *\n * The 'dirty' flag is set when any form element is modified within a watched form.\n * The flag can also be set programatically. This may be required for custom form elements.\n *\n * It is not possible to customise the warning message in any modern browser.\n *\n * Please note that some browsers have controls on when these alerts may or may not be shown.\n * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload} for browser-specific\n * notes and references.\n *\n * @module core_form/changechecker\n * @copyright 2021 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @example Usage where the FormElement is already held\n *\n * import {watchForm} from 'core_form/changechecker';\n *\n * // Fetch the form element somehow.\n * watchForm(formElement);\n *\n * @example Usage from the child of a form - i.e. an input, button, div, etc.\n *\n * import {watchForm} from 'core_form/changechecker';\n *\n * // Watch the form by using a child of it.\n * watchForm(document.querySelector('input[data-foo=\"bar\"]'););\n *\n * @example Usage from within a template\n *
\n * \n *
\n * {{#js}}\n * require(['core_form/changechecker'], function(changeChecker) {\n * watchFormById('mod_example-entry-{{uniqid}}');\n * });\n * {{/js}}\n */\n\nimport {eventTypes} from 'core_editor/events';\nimport {getString} from 'core/str';\n\n/**\n * @property {Bool} initialised Whether the change checker has been initialised\n * @private\n */\nlet initialised = false;\n\n/**\n * @property {String} warningString The warning string to show on form change failure\n * @private\n */\nlet warningString;\n\n/**\n * @property {Array} watchedForms The list of watched forms\n * @private\n */\nlet watchedForms = [];\n\n/**\n * @property {Bool} formChangeCheckerDisabled Whether the form change checker has been actively disabled\n * @private\n */\nlet formChangeCheckerDisabled = false;\n\n/**\n * Get the nearest form element from a child element.\n *\n * @param {HTMLElement} formChild\n * @returns {HTMLFormElement|null}\n * @private\n */\nconst getFormFromChild = formChild => formChild.closest('form');\n\n/**\n * Watch the specified form for changes.\n *\n * @method\n * @param {HTMLElement} formNode\n */\nexport const watchForm = formNode => {\n // Normalise the formNode.\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n // No form found.\n return;\n }\n\n if (isWatchingForm(formNode)) {\n // This form is already watched.\n return;\n }\n\n watchedForms.push(formNode);\n};\n\n/**\n * Stop watching the specified form for changes.\n *\n * If the form was not watched, then no change is made.\n *\n * A child of the form may be passed instead.\n *\n * @method\n * @param {HTMLElement} formNode\n * @example Stop watching a form for changes\n * import {unWatchForm} from 'core_form/changechecker';\n *\n * // ...\n * document.addEventListener('click', e => {\n * if (e.target.closest('[data-action=\"changePage\"]')) {\n * unWatchForm(e.target);\n * }\n * });\n */\nexport const unWatchForm = formNode => {\n watchedForms = watchedForms.filter(watchedForm => !!watchedForm.contains(formNode));\n};\n\n/**\n * Reset the 'dirty' flag for all watched forms.\n *\n * If a form was previously marked as 'dirty', then this flag will be cleared and when the page is unloaded no warning\n * will be shown.\n *\n * @method\n */\nexport const resetAllFormDirtyStates = () => {\n watchedForms.forEach(watchedForm => {\n watchedForm.dataset.formSubmitted = \"false\";\n watchedForm.dataset.formDirty = \"false\";\n });\n};\n\n/**\n * Reset the 'dirty' flag of the specified form.\n *\n * @method\n * @param {HTMLElement} formNode\n */\nexport const resetFormDirtyState = formNode => {\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n return;\n }\n\n formNode.dataset.formSubmitted = \"false\";\n formNode.dataset.formDirty = \"false\";\n};\n\n/**\n * Mark all forms as dirty.\n *\n * This function is only for backwards-compliance with the old YUI module and should not be used in any other situation.\n * It will be removed in Moodle 4.4.\n *\n * @method\n */\nexport const markAllFormsAsDirty = () => {\n watchedForms.forEach(watchedForm => {\n watchedForm.dataset.formDirty = \"true\";\n });\n};\n\n/**\n * Mark a specific form as dirty.\n *\n * This behaviour may be required for custom form elements which are not caught by the standard change listeners.\n *\n * @method\n * @param {HTMLElement} formNode\n */\nexport const markFormAsDirty = formNode => {\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n return;\n }\n\n // Mark it as dirty.\n formNode.dataset.formDirty = \"true\";\n};\n\n/**\n * Actively disable the form change checker.\n *\n * Please note that it cannot be re-enabled once disabled.\n *\n * @method\n */\nexport const disableAllChecks = () => {\n formChangeCheckerDisabled = true;\n};\n\n/**\n * Check whether any watched from is dirty.\n *\n * @method\n * @returns {Bool}\n */\nexport const isAnyWatchedFormDirty = () => {\n if (formChangeCheckerDisabled) {\n // The form change checker is disabled.\n return false;\n }\n\n const hasSubmittedForm = watchedForms.some(watchedForm => watchedForm.dataset.formSubmitted === \"true\");\n if (hasSubmittedForm) {\n // Do not warn about submitted forms, ever.\n return false;\n }\n\n const hasDirtyForm = watchedForms.some(watchedForm => {\n if (!watchedForm.isConnected) {\n // The watched form is not connected to the DOM.\n return false;\n }\n\n if (watchedForm.dataset.formDirty === \"true\") {\n // The form has been marked as dirty.\n return true;\n }\n\n // Elements currently holding focus will not have triggered change detection.\n // Check whether the value matches the original value upon form load.\n if (document.activeElement && document.activeElement.dataset.propertyIsEnumerable('initialValue')) {\n const isActiveElementWatched = isWatchingForm(document.activeElement)\n && !shouldIgnoreChangesForNode(document.activeElement);\n const hasValueChanged = document.activeElement.dataset.initialValue !== document.activeElement.value;\n\n if (isActiveElementWatched && hasValueChanged) {\n return true;\n }\n }\n\n return false;\n });\n\n if (hasDirtyForm) {\n // At least one form is dirty.\n return true;\n }\n\n // Handle TinyMCE editor instances.\n // TinyMCE forms may not have been initialised at the time that startWatching is called.\n // Check whether any tinyMCE editor is dirty.\n if (typeof window.tinyMCE !== 'undefined' && window.tinyMCE.editors) {\n if (window.tinyMCE.editors.some(editor => editor.isDirty())) {\n return true;\n }\n }\n\n // No dirty forms detected.\n return false;\n};\n\n/**\n * Get the watched form for the specified target.\n *\n * @method\n * @param {HTMLNode} target\n * @returns {HTMLFormElement}\n * @private\n */\nconst getFormForNode = target => watchedForms.find(watchedForm => watchedForm.contains(target));\n\n/**\n * Whether the specified target is a watched form.\n *\n * @method\n * @param {HTMLNode} target\n * @returns {Bool}\n * @private\n */\nconst isWatchingForm = target => watchedForms.some(watchedForm => watchedForm.contains(target));\n\n/**\n * Whether the specified target should ignore changes or not.\n *\n * @method\n * @param {HTMLNode} target\n * @returns {Bool}\n * @private\n */\nconst shouldIgnoreChangesForNode = target => !!target.closest('.ignoredirty');\n\n/**\n * Mark a form as changed.\n *\n * @method\n * @param {HTMLElement} changedNode An element in the form which was changed\n */\nexport const markFormChangedFromNode = changedNode => {\n if (changedNode.dataset.formChangeCheckerOverride) {\n // Changes to this form node disable the form change checker entirely.\n // This is intended for select fields which cause an immediate redirect.\n disableAllChecks();\n return;\n }\n\n if (!isWatchingForm(changedNode)) {\n return;\n }\n\n if (shouldIgnoreChangesForNode(changedNode)) {\n return;\n }\n\n // Mark the form as dirty.\n const formNode = getFormForNode(changedNode);\n formNode.dataset.formDirty = \"true\";\n};\n\n/**\n * Mark a form as submitted.\n *\n * @method\n * @param {HTMLElement} formNode An element in the form to mark as submitted\n */\nexport const markFormSubmitted = formNode => {\n formNode = getFormFromChild(formNode);\n\n if (!formNode) {\n return;\n }\n\n formNode.dataset.formSubmitted = \"true\";\n};\n\n/**\n * Mark all forms as submitted.\n *\n * This function is only for backwards-compliance with the old YUI module and should not be used in any other situation.\n * It will be removed in Moodle 4.4.\n *\n * @method\n */\nexport const markAllFormsSubmitted = () => {\n watchedForms.forEach(watchedForm => markFormSubmitted(watchedForm));\n};\n\n/**\n * Handle the beforeunload event.\n *\n * @method\n * @param {Event} e\n * @returns {string|null}\n * @private\n */\nconst beforeUnloadHandler = e => {\n // Please note: The use of Promises in this function is forbidden.\n // This is an event handler and _cannot_ be asynchronous.\n let warnBeforeUnload = isAnyWatchedFormDirty() && !M.cfg.behatsiterunning;\n if (warnBeforeUnload) {\n // According to the specification, to show the confirmation dialog an event handler should call preventDefault()\n // on the event.\n e.preventDefault();\n\n // However note that not all browsers support this method, and some instead require the event handler to\n // implement one of two legacy methods:\n // * assigning a string to the event's returnValue property; and\n // * returning a string from the event handler.\n\n // Assigning a string to the event's returnValue property.\n e.returnValue = warningString;\n\n // Returning a string from the event handler.\n return e.returnValue;\n }\n\n // Attaching an event handler/listener to window or document's beforeunload event prevents browsers from using\n // in-memory page navigation caches, like Firefox's Back-Forward cache or WebKit's Page Cache.\n // Remove the handler.\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n\n return null;\n};\n\n/**\n * Start watching for form changes.\n *\n * This function is called on module load, and should not normally be called.\n *\n * @method\n * @protected\n */\nexport const startWatching = () => {\n if (initialised) {\n return;\n }\n\n document.addEventListener('change', e => {\n if (!isWatchingForm(e.target)) {\n return;\n }\n\n markFormChangedFromNode(e.target);\n });\n\n document.addEventListener('click', e => {\n const ignoredButton = e.target.closest('[data-formchangechecker-ignore-submit]');\n if (!ignoredButton) {\n return;\n }\n\n const ownerForm = getFormFromChild(e.target);\n if (ownerForm) {\n ownerForm.dataset.ignoreSubmission = \"true\";\n }\n });\n\n document.addEventListener('focusin', e => {\n if (e.target.matches('input, textarea, select')) {\n if (e.target.dataset.propertyIsEnumerable('initialValue')) {\n // The initial value has already been set.\n return;\n }\n e.target.dataset.initialValue = e.target.value;\n }\n });\n\n document.addEventListener('submit', e => {\n const formNode = getFormFromChild(e.target);\n if (!formNode) {\n // Weird, but watch for this anyway.\n return;\n }\n\n if (formNode.dataset.ignoreSubmission) {\n // This form was submitted by a button which requested that the form checked should not mark it as submitted.\n formNode.dataset.ignoreSubmission = \"false\";\n return;\n }\n\n markFormSubmitted(formNode);\n });\n\n document.addEventListener(eventTypes.editorContentRestored, e => {\n if (e.target != document) {\n resetFormDirtyState(e.target);\n } else {\n resetAllFormDirtyStates();\n }\n });\n\n getString('changesmadereallygoaway', 'moodle')\n .then(changesMadeString => {\n warningString = changesMadeString;\n return;\n })\n .catch();\n\n window.addEventListener('beforeunload', beforeUnloadHandler);\n};\n\n/**\n * Watch the form matching the specified ID for changes.\n *\n * @method\n * @param {String} formId\n */\nexport const watchFormById = formId => {\n watchForm(document.getElementById(formId));\n};\n\n/**\n * Reset the dirty state of the form matching the specified ID..\n *\n * @method\n * @param {String} formId\n */\nexport const resetFormDirtyStateById = formId => {\n resetFormDirtyState(document.getElementById(formId));\n};\n\n/**\n * Mark the form matching the specified ID as dirty.\n *\n * @method\n * @param {String} formId\n */\nexport const markFormAsDirtyById = formId => {\n markFormAsDirty(document.getElementById(formId));\n};\n\n// Configure all event listeners.\nstartWatching();\n"],"names":["warningString","watchedForms","formChangeCheckerDisabled","getFormFromChild","formChild","closest","watchForm","formNode","isWatchingForm","push","filter","watchedForm","contains","resetAllFormDirtyStates","forEach","dataset","formSubmitted","formDirty","resetFormDirtyState","markFormAsDirty","disableAllChecks","isAnyWatchedFormDirty","some","isConnected","document","activeElement","propertyIsEnumerable","isActiveElementWatched","shouldIgnoreChangesForNode","hasValueChanged","initialValue","value","window","tinyMCE","editors","editor","isDirty","target","markFormChangedFromNode","changedNode","formChangeCheckerOverride","find","markFormSubmitted","beforeUnloadHandler","e","M","cfg","behatsiterunning","preventDefault","returnValue","removeEventListener","startWatching","addEventListener","ownerForm","ignoreSubmission","matches","eventTypes","editorContentRestored","then","changesMadeString","catch","formId","getElementById"],"mappings":"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"} \ No newline at end of file diff --git a/lib/form/amd/src/changechecker.js b/lib/form/amd/src/changechecker.js index 2cd64fcdd7e..c4aa6f82378 100644 --- a/lib/form/amd/src/changechecker.js +++ b/lib/form/amd/src/changechecker.js @@ -418,9 +418,6 @@ export const startWatching = () => { return; } - // Add legacy support to provide b/c for the old YUI version. - addLegacyFunctions(); - document.addEventListener('change', e => { if (!isWatchingForm(e.target)) { return; @@ -485,33 +482,6 @@ export const startWatching = () => { window.addEventListener('beforeunload', beforeUnloadHandler); }; -/** - * Add legacy functions for backwards compatability. - * - * @method - * @private - */ -const addLegacyFunctions = () => { - // Create a curried function to log use of the old function and provide detail on its replacement. - const getLoggedLegacyFallback = (oldFunctionName, newFunctionName, newFunction) => (...args) => { - window.console.warn( - `The moodle-core-formchangechecker has been deprecated ` + - `and replaced with core_form/changechecker. ` + - `The ${oldFunctionName} function has been replaced with ${newFunctionName}.` - ); - newFunction(...args); - }; - - /* eslint-disable */ - window.M.core_formchangechecker = { - init: getLoggedLegacyFallback('init', 'watchFormById', watchFormById), - reset_form_dirty_state: getLoggedLegacyFallback('reset_form_dirty_state', 'resetFormDirtyState', resetAllFormDirtyStates), - set_form_changed: getLoggedLegacyFallback('set_form_changed', 'markFormAsDirty', markAllFormsAsDirty), - set_form_submitted: getLoggedLegacyFallback('set_form_submitted', 'markFormSubmitted', markAllFormsSubmitted), - }; - /* eslint-enable */ -}; - /** * Watch the form matching the specified ID for changes. * diff --git a/lib/form/upgrade.txt b/lib/form/upgrade.txt index b4a302be108..ce8d4ddb9f9 100644 --- a/lib/form/upgrade.txt +++ b/lib/form/upgrade.txt @@ -9,6 +9,8 @@ information provided here is intended especially for developers. which the previous `enhance` is now a wrapper of, while preserving jQuery promise return) * The group element has a new method `getAttributesForFormElement` which should be used in conjunction with `createFormElement` to ensure that all elements within the group have unique IDs +* The deprecated `moodle-core-formchangechecker` YUI module and legacy `M.core_formchangechecker` have been + removed and can no longer be used === 4.3 === diff --git a/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-debug.js b/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-debug.js deleted file mode 100644 index 61da4e2f703..00000000000 --- a/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-debug.js +++ /dev/null @@ -1,73 +0,0 @@ -YUI.add('moodle-core-formchangechecker', function (Y, NAME) { - -/** - * A utility to check for form changes before navigating away from a page. - * - * @module moodle-core-formchangechecker - */ - -/** - * A utility to check for form changes before navigating away from a page. - * - * Please note that this YUI module has been deprecated in favour of the core_form/changechecker AMD module. - * - * @class M.core.formchangechecker - * @deprecated - */ - -window.console.warn( - 'The moodle-core-formchangechecker has been deprecated ' + - 'and replaced with core_form/changechecker. ' + - 'Please update your code to make use of the new module.' -); - -require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.startWatching(); -}); - -// The following are provided to prevent race conditions. -// Because the AMD module is loaded asynchronously after the YUI module is loaded, there is a possibility that the -// calling code may call the YUI function calls before the AMD module has finished loading. -// These will be removed in future and are automatically overwritten by the legacy helper provided as part of the new -// changechecker AMD module. -// eslint-disable-next-line camelcase -M.core_formchangechecker = M.core_formchangechecker || { - init: function(config) { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.watchFormById(config.formid); - }); - }, - - /** - * Set the form changed state to true - */ - // eslint-disable-next-line camelcase - set_form_changed: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.markAllFormsAsDirty(); - }); - }, - - /** - * Set the form submitted state to true - */ - // eslint-disable-next-line camelcase - set_form_submitted: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.markAllFormsSubmitted(); - }); - }, - - /** - * Reset the form state - */ - // eslint-disable-next-line camelcase - reset_form_dirty_state: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.resetAllFormDirtyStates(); - }); - }, -}; - - -}, '@VERSION@', {"requires": ["base", "event-focus", "moodle-core-event"]}); diff --git a/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-min.js b/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-min.js deleted file mode 100644 index 4f08967838a..00000000000 --- a/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-min.js +++ /dev/null @@ -1 +0,0 @@ -YUI.add("moodle-core-formchangechecker",function(e,r){window.console.warn("The moodle-core-formchangechecker has been deprecated and replaced with core_form/changechecker. Please update your code to make use of the new module."),require(["core_form/changechecker"],function(e){e.startWatching()}),M.core_formchangechecker=M.core_formchangechecker||{init:function(r){require(["core_form/changechecker"],function(e){e.watchFormById(r.formid)})},set_form_changed:function(){require(["core_form/changechecker"],function(e){e.markAllFormsAsDirty()})},set_form_submitted:function(){require(["core_form/changechecker"],function(e){e.markAllFormsSubmitted()})},reset_form_dirty_state:function(){require(["core_form/changechecker"],function(e){e.resetAllFormDirtyStates()})}}},"@VERSION@",{requires:["base","event-focus","moodle-core-event"]}); \ No newline at end of file diff --git a/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker.js b/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker.js deleted file mode 100644 index 61da4e2f703..00000000000 --- a/lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker.js +++ /dev/null @@ -1,73 +0,0 @@ -YUI.add('moodle-core-formchangechecker', function (Y, NAME) { - -/** - * A utility to check for form changes before navigating away from a page. - * - * @module moodle-core-formchangechecker - */ - -/** - * A utility to check for form changes before navigating away from a page. - * - * Please note that this YUI module has been deprecated in favour of the core_form/changechecker AMD module. - * - * @class M.core.formchangechecker - * @deprecated - */ - -window.console.warn( - 'The moodle-core-formchangechecker has been deprecated ' + - 'and replaced with core_form/changechecker. ' + - 'Please update your code to make use of the new module.' -); - -require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.startWatching(); -}); - -// The following are provided to prevent race conditions. -// Because the AMD module is loaded asynchronously after the YUI module is loaded, there is a possibility that the -// calling code may call the YUI function calls before the AMD module has finished loading. -// These will be removed in future and are automatically overwritten by the legacy helper provided as part of the new -// changechecker AMD module. -// eslint-disable-next-line camelcase -M.core_formchangechecker = M.core_formchangechecker || { - init: function(config) { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.watchFormById(config.formid); - }); - }, - - /** - * Set the form changed state to true - */ - // eslint-disable-next-line camelcase - set_form_changed: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.markAllFormsAsDirty(); - }); - }, - - /** - * Set the form submitted state to true - */ - // eslint-disable-next-line camelcase - set_form_submitted: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.markAllFormsSubmitted(); - }); - }, - - /** - * Reset the form state - */ - // eslint-disable-next-line camelcase - reset_form_dirty_state: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.resetAllFormDirtyStates(); - }); - }, -}; - - -}, '@VERSION@', {"requires": ["base", "event-focus", "moodle-core-event"]}); diff --git a/lib/yui/src/formchangechecker/build.json b/lib/yui/src/formchangechecker/build.json deleted file mode 100644 index 6fa6ccfc471..00000000000 --- a/lib/yui/src/formchangechecker/build.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "moodle-core-formchangechecker", - "builds": { - "moodle-core-formchangechecker": { - "jsfiles": [ - "formchangechecker.js" - ] - } - } -} diff --git a/lib/yui/src/formchangechecker/js/formchangechecker.js b/lib/yui/src/formchangechecker/js/formchangechecker.js deleted file mode 100644 index 28aea11d85b..00000000000 --- a/lib/yui/src/formchangechecker/js/formchangechecker.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * A utility to check for form changes before navigating away from a page. - * - * @module moodle-core-formchangechecker - */ - -/** - * A utility to check for form changes before navigating away from a page. - * - * Please note that this YUI module has been deprecated in favour of the core_form/changechecker AMD module. - * - * @class M.core.formchangechecker - * @deprecated - */ - -window.console.warn( - 'The moodle-core-formchangechecker has been deprecated ' + - 'and replaced with core_form/changechecker. ' + - 'Please update your code to make use of the new module.' -); - -require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.startWatching(); -}); - -// The following are provided to prevent race conditions. -// Because the AMD module is loaded asynchronously after the YUI module is loaded, there is a possibility that the -// calling code may call the YUI function calls before the AMD module has finished loading. -// These will be removed in future and are automatically overwritten by the legacy helper provided as part of the new -// changechecker AMD module. -// eslint-disable-next-line camelcase -M.core_formchangechecker = M.core_formchangechecker || { - init: function(config) { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.watchFormById(config.formid); - }); - }, - - /** - * Set the form changed state to true - */ - // eslint-disable-next-line camelcase - set_form_changed: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.markAllFormsAsDirty(); - }); - }, - - /** - * Set the form submitted state to true - */ - // eslint-disable-next-line camelcase - set_form_submitted: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.markAllFormsSubmitted(); - }); - }, - - /** - * Reset the form state - */ - // eslint-disable-next-line camelcase - reset_form_dirty_state: function() { - require(['core_form/changechecker'], function(ChangeChecker) { - ChangeChecker.resetAllFormDirtyStates(); - }); - }, -}; diff --git a/lib/yui/src/formchangechecker/meta/formchangechecker.json b/lib/yui/src/formchangechecker/meta/formchangechecker.json deleted file mode 100644 index 8490d8bc38b..00000000000 --- a/lib/yui/src/formchangechecker/meta/formchangechecker.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moodle-core-formchangechecker": { - "requires": [ - "base", - "event-focus", - "moodle-core-event" - ] - } -}