diff --git a/lib/amd/build/tag.min.js b/lib/amd/build/tag.min.js
index 328a923d1b6..ad1a96a3baf 100644
--- a/lib/amd/build/tag.min.js
+++ b/lib/amd/build/tag.min.js
@@ -1,11 +1,11 @@
+define("core/tag",["exports","jquery","core/ajax","core/notification","core/templates","core/str","core/modal_events","core/pending","core/modal_save_cancel","core/config"],(function(_exports,_jquery,_ajax,Notification,Templates,_str,ModalEvents,_pending,_modal_save_cancel,_config){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
- * AJAX helper for the tag management page.
- *
- * @module core/tag
- * @copyright 2015 Marina Glancy
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @since 3.0
- */
-define("core/tag",["jquery","core/ajax","core/templates","core/notification","core/str","core/modal_save_cancel","core/modal_events","core/pending"],(function($,ajax,templates,notification,str,SaveCancelModal,ModalEvents,Pending){return{initTagindexPage:function(){$("body").delegate(".tagarea[data-ta] a[data-quickload=1]","click",(function(e){var pendingPromise=new Pending("core/tag:initTagindexPage");e.preventDefault();var target=$(this),query=target[0].search.replace(/^\?/,""),tagarea=target.closest(".tagarea[data-ta]"),args=query.split("&").reduce((function(s,c){var t=c.split("=");return s[t[0]]=decodeURIComponent(t[1]),s}),{});ajax.call([{methodname:"core_tag_get_tagindex",args:{tagindex:args}}])[0].then((function(data){return templates.render("core_tag/index",data)})).then((function(html,js){templates.replaceNode(tagarea,html,js)})).always(pendingPromise.resolve).catch(notification.exception)}))},initManagePage:function(){$("body").on("updated","[data-inplaceeditable]",(function(e){var pendingPromise=new Pending("core/tag:initManagePage");if(str.get_strings([{key:"selecttag",component:"core_tag"},{key:"now",component:"core"}]).then((function(result){$('label[for="tagselect'+e.ajaxreturn.itemid+'"]').html(result[0]),$(e.target).closest("tr").find("td.col-timemodified").html(result[1])})).always(pendingPromise.resolve).catch(notification.exception),"tagflag"===e.ajaxreturn.itemtype){var row=$(e.target).closest("tr");"0"===e.ajaxreturn.value?row.removeClass("table-warning"):row.addClass("table-warning")}})),$(".tag-management-table").delegate("a.tagdelete","click",(function(e){var pendingPromise=new Pending("core/tag:tagdelete");e.preventDefault();var href=$(this).attr("href");str.get_strings([{key:"delete",component:"core"},{key:"confirmdeletetag",component:"tag"},{key:"yes",component:"core"},{key:"no",component:"core"}]).then((function(s){return notification.confirm(s[0],s[1],s[2],s[3],(function(){window.location.href=href}))})).always(pendingPromise.resolve).catch(notification.exception)})),$("#tag-management-delete").click((function(e){var form=$(this).closest("form").get(0);if($(form).find("input[data-togglegroup='tags-manage'][data-toggle='slave']:checked").length){var pendingPromise=new Pending("core/tag:tag-management-delete"),tempElement=$("").attr("name",this.name);e.preventDefault(),str.get_strings([{key:"delete",component:"core"},{key:"confirmdeletetags",component:"tag"},{key:"yes",component:"core"},{key:"no",component:"core"}]).then((function(s){return notification.confirm(s[0],s[1],s[2],s[3],(function(){tempElement.appendTo(form),form.submit()}))})).always(pendingPromise.resolve).catch(notification.exception)}})),$("#tag-management-combine").click((function(e){var pendingPromise=new Pending("core/tag:tag-management-combine");e.preventDefault();var form=$(this).closest("form").get(0),tags=$(form).find("input[data-togglegroup='tags-manage'][data-toggle='slave']:checked");if(tags.length<=1)str.get_strings([{key:"combineselected",component:"tag"},{key:"selectmultipletags",component:"tag"},{key:"ok"}]).then((function(s){return notification.alert(s[0],s[1],s[2])})).always(pendingPromise.resolve).catch(notification.exception);else{var tempElement=$("").attr("name",this.name),saveButtonText="",tagOptions=[];tags.each((function(){var tagid=$(this).val(),tagname=$(".inplaceeditable[data-itemtype=tagname][data-itemid="+tagid+"]").attr("data-value");tagOptions.push({id:tagid,name:tagname})})),str.get_strings([{key:"combineselected",component:"tag"},{key:"continue",component:"core"}]).then((function(langStrings){var modalTitle=langStrings[0];saveButtonText=langStrings[1];var templateContext={tags:tagOptions};return SaveCancelModal.create({title:modalTitle,body:templates.render("core_tag/combine_tags",templateContext),buttons:{save:saveButtonText},show:!0,removeOnClose:!0})})).then((function(modal){modal.getRoot().on(ModalEvents.save,(function(e){e.preventDefault(),tempElement.appendTo(form);var maintag=$("input[name=maintag]:checked","#combinetags_form").val();$("").attr("name","maintag").attr("value",maintag).appendTo(form),form.submit()})),$("#combinetags_form input[type=radio]").first().focus().prop("checked",!0)})).always(pendingPromise.resolve).catch(notification.exception)}})),$("body").on("updatefailed","[data-inplaceeditable][data-itemtype=tagname]",(function(e){var exception=e.exception,newvalue=e.newvalue,tagid=$(e.target).attr("data-itemid");if("namesalreadybeeingused"===exception.errorcode){var pendingPromise=new Pending("core/tag:updatefailed");e.preventDefault(),str.get_strings([{key:"confirm",component:"core"},{key:"nameuseddocombine",component:"tag"},{key:"yes",component:"core"},{key:"cancel",component:"core"}]).then((function(s){return notification.confirm(s[0],s[1],s[2],s[3],(function(){window.location.href=window.location.href+"&newname="+encodeURIComponent(newvalue)+"&tagid="+encodeURIComponent(tagid)+"&action=renamecombine&sesskey="+M.cfg.sesskey}))})).always(pendingPromise.resolve).catch(notification.exception)}})),$("body").on("click","a[data-action=addstandardtag]",(function(e){var pendingPromise=new Pending("core/tag:addstandardtag");return e.preventDefault(),SaveCancelModal.create({title:str.get_string("addotags","tag"),body:templates.render("core_tag/add_tags",{actionurl:window.location.href,sesskey:M.cfg.sesskey}),buttons:{save:str.get_string("continue","core")},show:!0,removeOnClose:!0}).then((function(modal){modal.getRoot().on(ModalEvents.save,(function(e){var tagsInput=$(e.currentTarget).find("#id_tagslist"),name=tagsInput.val().trim();tagsInput.val(name);var tagsForm=$("#addtags_form");return tagsForm.on("submit",(function(e){var form=$("#addtags_form");!1===form[0].checkValidity()&&(e.preventDefault(),e.stopPropagation()),form.addClass("was-validated"),$('[data-region="tagslistinput"]').addClass("error");var errorMessage=$("#id_tagslist_error_message");errorMessage.removeAttr("hidden"),errorMessage.addClass("help-block")})),tagsForm.submit(),!1}))})).always(pendingPromise.resolve).catch(notification.exception)}))},initManageCollectionsPage:function(){$("body").on("updated","[data-inplaceeditable]",(function(e){var areaid,collid,pendingPromise=new Pending("core/tag:initManageCollectionsPage-updated"),ajaxreturn=e.ajaxreturn;"core_tag"===ajaxreturn.component&&"tagareaenable"===ajaxreturn.itemtype&&(areaid=$(this).attr("data-itemid"),$(".tag-collections-table ul[data-collectionid] li[data-areaid="+areaid+"]").hide(),"1"===ajaxreturn.value?($(this).closest("tr").removeClass("dimmed_text"),collid=$(this).closest("tr").find('[data-itemtype="tagareacollection"]').attr("data-value"),$(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]").show()):$(this).closest("tr").addClass("dimmed_text")),"core_tag"===ajaxreturn.component&&"tagareacollection"===ajaxreturn.itemtype&&(areaid=$(this).attr("data-itemid"),$(".tag-collections-table ul[data-collectionid] li[data-areaid="+areaid+"]").hide(),collid=$(this).attr("data-value"),"1"===$(this).closest("tr").find('[data-itemtype="tagareaenable"]').attr("data-value")&&$(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]").show()),pendingPromise.resolve()})),$("body").on("click",".addtagcoll > a",(function(e){var pendingPromise=new Pending("core/tag:initManageCollectionsPage-addtagcoll");e.preventDefault();var href=$(this).attr("data-url"),saveButtonText="";str.get_strings([{key:"addtagcoll",component:"tag"},{key:"create",component:"core"}]).then((function(langStrings){var modalTitle=langStrings[0];saveButtonText=langStrings[1];var templateContext={actionurl:href,sesskey:M.cfg.sesskey};return SaveCancelModal.create({title:modalTitle,body:templates.render("core_tag/add_tag_collection",templateContext),buttons:{save:saveButtonText},show:!0,removeOnClose:!0})})).then((function(modal){return modal.getRoot().on(ModalEvents.save,(function(e){var collectionInput=$(e.currentTarget).find("#addtagcoll_name"),name=collectionInput.val().trim();collectionInput.val(name);var form=$("#addtagcoll_form");return form.on("submit",(function(e){!1===form[0].checkValidity()&&(e.preventDefault(),e.stopPropagation()),form.addClass("was-validated"),$('[data-region="addtagcoll_nameinput"]').addClass("error");var errorMessage=$("#id_addtagcoll_name_error_message");errorMessage.removeAttr("hidden"),errorMessage.addClass("help-block")})),form.submit(),!1})),modal})).always(pendingPromise.resolve).catch(notification.exception)})),$("body").on("click",".tag-collections-table .action_delete",(function(e){var pendingPromise=new Pending("core/tag:initManageCollectionsPage-action_delete");e.preventDefault();var href=$(this).attr("data-url")+"&sesskey="+M.cfg.sesskey;str.get_strings([{key:"delete"},{key:"suredeletecoll",component:"tag",param:$(this).attr("data-collname")},{key:"yes"},{key:"no"}]).then((function(s){return notification.confirm(s[0],s[1],s[2],s[3],(function(){window.location.href=href}))})).always(pendingPromise.resolve).catch(notification.exception)}))}}}));
+ * AJAX helper for the tag management page.
+ *
+ * @module core/tag
+ * @copyright 2015 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since 3.0
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.initTagindexPage=_exports.initManagePage=_exports.initManageCollectionsPage=void 0,_jquery=_interopRequireDefault(_jquery),Notification=_interopRequireWildcard(Notification),Templates=_interopRequireWildcard(Templates),ModalEvents=_interopRequireWildcard(ModalEvents),_pending=_interopRequireDefault(_pending),_modal_save_cancel=_interopRequireDefault(_modal_save_cancel),_config=_interopRequireDefault(_config);const getCheckedTags=form=>form.querySelectorAll('input[data-togglegroup="tags-manage"][data-toggle="slave"]:checked');_exports.initTagindexPage=async()=>{document.addEventListener("click",(async e=>{const targetArea=e.target.closest('a[data-quickload="1"]');if(!targetArea)return;const tagArea=targetArea.closest(".tagarea[data-ta]");if(!tagArea)return;e.preventDefault();const pendingPromise=new _pending.default("core/tag:initTagindexPage"),query=targetArea.search.replace(/^\?/,""),params=Object.fromEntries(new URLSearchParams(query).entries());try{const data=await(tagindex=params,(0,_ajax.call)([{methodname:"core_tag_get_tagindex",args:{tagindex:tagindex}}])[0]),{html:html,js:js}=await Templates.renderForPromise("core_tag/index",data);Templates.replaceNode(tagArea,html,js)}catch(error){Notification.exception(error)}var tagindex;pendingPromise.resolve()}))};_exports.initManagePage=()=>{(0,_jquery.default)("body").on("updated","[data-inplaceeditable]",(function(e){var pendingPromise=new _pending.default("core/tag:initManagePage");if((0,_str.get_strings)([{key:"selecttag",component:"core_tag"},{key:"now",component:"core"}]).then((function(result){(0,_jquery.default)('label[for="tagselect'+e.ajaxreturn.itemid+'"]').html(result[0]),(0,_jquery.default)(e.target).closest("tr").find("td.col-timemodified").html(result[1])})).always(pendingPromise.resolve).catch(Notification.exception),"tagflag"===e.ajaxreturn.itemtype){var row=(0,_jquery.default)(e.target).closest("tr");"0"===e.ajaxreturn.value?row.removeClass("table-warning"):row.addClass("table-warning")}})),document.addEventListener("click",(async e=>{const tagManagementCombine=e.target.closest("#tag-management-combine");tagManagementCombine&&(e.preventDefault(),(async tagManagementCombine=>{const pendingPromise=new _pending.default("core/tag:tag-management-combine"),form=tagManagementCombine.closest("form"),checkedTags=getCheckedTags(form);if(checkedTags.length<=1)return void Notification.alert((0,_str.get_string)("combineselected","tag"),(0,_str.get_string)("selectmultipletags","tag"),(0,_str.get_string)("ok"));const tags=Array.from(checkedTags.values()).map((tag=>{const namedElement=document.querySelector('.inplaceeditable[data-itemtype=tagname][data-itemid="'.concat(tag.value,'"]'));return{id:tag.value,name:namedElement.dataset.value}})),modal=await _modal_save_cancel.default.create({title:(0,_str.get_string)("combineselected","tag"),buttons:{save:(0,_str.get_string)("continue","core")},body:Templates.render("core_tag/combine_tags",{tags:tags}),show:!0,removeOnClose:!0});modal.getRoot().on(ModalEvents.save,(e=>{e.preventDefault();const tempElement=document.createElement("input");tempElement.hidden=!0,tempElement.name=tagManagementCombine.name,form.append(tempElement);var maintag=(0,_jquery.default)("input[name=maintag]:checked","#combinetags_form").val();(0,_jquery.default)("").attr("name","maintag").attr("value",maintag).appendTo(form),form.submit()})),await modal.getBodyPromise();const firstOption=document.querySelector("#combinetags_form input[type=radio]");firstOption.focus(),firstOption.checked=!0,pendingPromise.resolve()})(tagManagementCombine)),e.target.closest('a[data-action="addstandardtag"]')&&(e.preventDefault(),(async()=>{var pendingPromise=new _pending.default("core/tag:addstandardtag");const modal=await _modal_save_cancel.default.create({title:(0,_str.get_string)("addotags","tag"),body:Templates.render("core_tag/add_tags",{actionurl:window.location.href,sesskey:M.cfg.sesskey}),buttons:{save:(0,_str.get_string)("continue","core")},removeOnClose:!0,show:!0});modal.getRoot().on(ModalEvents.save,(e=>{var tagsInput=(0,_jquery.default)(e.currentTarget).find("#id_tagslist"),name=tagsInput.val().trim();tagsInput.val(name);var tagsForm=(0,_jquery.default)("#addtags_form");return tagsForm.on("submit",(function(e){var form=(0,_jquery.default)("#addtags_form");!1===form[0].checkValidity()&&(e.preventDefault(),e.stopPropagation()),form.addClass("was-validated"),(0,_jquery.default)('[data-region="tagslistinput"]').addClass("error");var errorMessage=(0,_jquery.default)("#id_tagslist_error_message");errorMessage.removeAttr("hidden"),errorMessage.addClass("help-block")})),tagsForm.submit(),!1})),await modal.getBodyPromise(),pendingPromise.resolve()})());const bulkActionDeleteButton=e.target.closest("#tag-management-delete");bulkActionDeleteButton&&(e.preventDefault(),(async form=>{if(getCheckedTags(form).length)try{await Notification.saveCancelPromise((0,_str.get_string)("delete"),(0,_str.get_string)("confirmdeletetags","tag"),(0,_str.get_string)("yes"),(0,_str.get_string)("no"));const tempElement=document.createElement("input");tempElement.hidden=!0,tempElement.name="bulkdelete",form.append(tempElement),form.submit()}catch{return}})(bulkActionDeleteButton.closest("form")));const rowDeleteButton=e.target.closest(".tagdelete");rowDeleteButton&&(e.preventDefault(),(async button=>{try{await Notification.saveCancelPromise((0,_str.get_string)("delete"),(0,_str.get_string)("confirmdeletetag","tag"),(0,_str.get_string)("yes"),(0,_str.get_string)("no")),window.location.href=button.href}catch{return}})(rowDeleteButton))})),(0,_jquery.default)("body").on("updatefailed","[data-inplaceeditable][data-itemtype=tagname]",(async e=>{var exception=e.exception,newvalue=e.newvalue,tagid=(0,_jquery.default)(e.target).attr("data-itemid");if("namesalreadybeeingused"===exception.errorcode){e.preventDefault();try{await Notification.saveCancelPromise((0,_str.get_string)("confirm"),(0,_str.get_string)("nameuseddocombine","tag"),(0,_str.get_string)("yes"),(0,_str.get_string)("cancel"));const redirectTarget=new URL(window.location);redirectTarget.searchParams.set("newname",newvalue),redirectTarget.searchParams.set("tagid",tagid),redirectTarget.searchParams.set("action","renamecombine"),redirectTarget.searchParams.set("sesskey",_config.default.sesskey),window.location.href=redirectTarget}catch{return}}}))};_exports.initManageCollectionsPage=()=>{(0,_jquery.default)("body").on("updated","[data-inplaceeditable]",(function(e){var areaid,collid,pendingPromise=new _pending.default("core/tag:initManageCollectionsPage-updated"),ajaxreturn=e.ajaxreturn;"core_tag"===ajaxreturn.component&&"tagareaenable"===ajaxreturn.itemtype&&(areaid=(0,_jquery.default)(this).attr("data-itemid"),(0,_jquery.default)(".tag-collections-table ul[data-collectionid] li[data-areaid="+areaid+"]").hide(),"1"===ajaxreturn.value?((0,_jquery.default)(this).closest("tr").removeClass("dimmed_text"),collid=(0,_jquery.default)(this).closest("tr").find('[data-itemtype="tagareacollection"]').attr("data-value"),(0,_jquery.default)(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]").show()):(0,_jquery.default)(this).closest("tr").addClass("dimmed_text")),"core_tag"===ajaxreturn.component&&"tagareacollection"===ajaxreturn.itemtype&&(areaid=(0,_jquery.default)(this).attr("data-itemid"),(0,_jquery.default)(".tag-collections-table ul[data-collectionid] li[data-areaid="+areaid+"]").hide(),collid=(0,_jquery.default)(this).attr("data-value"),"1"===(0,_jquery.default)(this).closest("tr").find('[data-itemtype="tagareaenable"]').attr("data-value")&&(0,_jquery.default)(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]").show()),pendingPromise.resolve()})),document.addEventListener("click",(async e=>{const addTagCollectionNode=e.target.closest(".addtagcoll > a");if(addTagCollectionNode)return e.preventDefault(),void(async link=>{const pendingPromise=new _pending.default("core/tag:initManageCollectionsPage-addtagcoll"),href=link.dataset.url;(await _modal_save_cancel.default.create({title:(0,_str.get_string)("addtagcoll","tag"),buttons:{save:(0,_str.get_string)("create","core")},body:Templates.render("core_tag/add_tag_collection",{actionurl:href,sesskey:M.cfg.sesskey}),removeOnClose:!0,show:!0})).getRoot().on(ModalEvents.save,(e=>{const collectionInput=(0,_jquery.default)(e.currentTarget).find("#addtagcoll_name"),name=collectionInput.val().trim();collectionInput.val(name);const form=(0,_jquery.default)("#addtagcoll_form");return form.on("submit",(function(e){!1===form[0].checkValidity()&&(e.preventDefault(),e.stopPropagation()),form.addClass("was-validated"),(0,_jquery.default)('[data-region="addtagcoll_nameinput"]').addClass("error");const errorMessage=(0,_jquery.default)("#id_addtagcoll_name_error_message");errorMessage.removeAttr("hidden"),errorMessage.addClass("help-block")})),form.submit(),!1})),pendingPromise.resolve()})(addTagCollectionNode);const deleteCollectionButton=e.target.closest(".tag-collections-table .action_delete");deleteCollectionButton&&(e.preventDefault(),(async button=>{try{await Notification.saveCancelPromise((0,_str.get_string)("delete"),(0,_str.get_string)("suredeletecoll","tag",button.dataset.collname),(0,_str.get_string)("yes"),(0,_str.get_string)("no"));const redirectTarget=new URL(button.dataset.url);redirectTarget.searchParams.set("sesskey",_config.default.sesskey),window.location.href=redirectTarget}catch{return}})(deleteCollectionButton))}))}}));
//# sourceMappingURL=tag.min.js.map
\ No newline at end of file
diff --git a/lib/amd/build/tag.min.js.map b/lib/amd/build/tag.min.js.map
index 2a5295636c7..a7b8f12e25e 100644
--- a/lib/amd/build/tag.min.js.map
+++ b/lib/amd/build/tag.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"tag.min.js","sources":["../src/tag.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 * AJAX helper for the tag management page.\n *\n * @module core/tag\n * @copyright 2015 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.0\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/modal_save_cancel',\n 'core/modal_events',\n 'core/pending',\n], function(\n $,\n ajax,\n templates,\n notification,\n str,\n SaveCancelModal,\n ModalEvents,\n Pending\n) {\n return /** @alias module:core/tag */ {\n\n /**\n * Initialises tag index page.\n *\n * @method initTagindexPage\n */\n initTagindexPage: function() {\n // Click handler for changing tag type.\n $('body').delegate('.tagarea[data-ta] a[data-quickload=1]', 'click', function(e) {\n var pendingPromise = new Pending('core/tag:initTagindexPage');\n\n e.preventDefault();\n var target = $(this);\n var query = target[0].search.replace(/^\\?/, '');\n var tagarea = target.closest('.tagarea[data-ta]');\n var args = query.split('&').reduce(function(s, c) {\n var t = c.split('=');\n s[t[0]] = decodeURIComponent(t[1]);\n return s;\n }, {});\n\n ajax.call([{\n methodname: 'core_tag_get_tagindex',\n args: {tagindex: args}\n }])[0]\n .then(function(data) {\n return templates.render('core_tag/index', data);\n })\n .then(function(html, js) {\n templates.replaceNode(tagarea, html, js);\n return;\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n });\n },\n\n /**\n * Initialises tag management page.\n *\n * @method initManagePage\n */\n initManagePage: function() {\n // Set cell 'time modified' to 'now' when any of the element is updated in this row.\n $('body').on('updated', '[data-inplaceeditable]', function(e) {\n var pendingPromise = new Pending('core/tag:initManagePage');\n\n str.get_strings([\n {\n key: 'selecttag',\n component: 'core_tag',\n },\n {\n key: 'now',\n component: 'core',\n },\n ])\n .then(function(result) {\n $('label[for=\"tagselect' + e.ajaxreturn.itemid + '\"]').html(result[0]);\n $(e.target).closest('tr').find('td.col-timemodified').html(result[1]);\n\n return;\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n\n if (e.ajaxreturn.itemtype === 'tagflag') {\n var row = $(e.target).closest('tr');\n if (e.ajaxreturn.value === '0') {\n row.removeClass('table-warning');\n } else {\n row.addClass('table-warning');\n }\n }\n });\n\n // Confirmation for single tag delete link.\n $('.tag-management-table').delegate('a.tagdelete', 'click', function(e) {\n var pendingPromise = new Pending('core/tag:tagdelete');\n\n e.preventDefault();\n var href = $(this).attr('href');\n str.get_strings([\n {key: 'delete', component: 'core'},\n {key: 'confirmdeletetag', component: 'tag'},\n {key: 'yes', component: 'core'},\n {key: 'no', component: 'core'},\n ])\n .then(function(s) {\n return notification.confirm(s[0], s[1], s[2], s[3], function() {\n window.location.href = href;\n });\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n });\n\n // Confirmation for bulk tag delete button.\n $(\"#tag-management-delete\").click(function(e) {\n var form = $(this).closest('form').get(0);\n\n var cnt = $(form).find(\"input[data-togglegroup='tags-manage'][data-toggle='slave']:checked\").length;\n if (!cnt) {\n return;\n }\n\n var pendingPromise = new Pending('core/tag:tag-management-delete');\n var tempElement = $(\"\").attr('name', this.name);\n e.preventDefault();\n str.get_strings([\n {key: 'delete', component: 'core'},\n {key: 'confirmdeletetags', component: 'tag'},\n {key: 'yes', component: 'core'},\n {key: 'no', component: 'core'},\n ])\n .then(function(s) {\n return notification.confirm(s[0], s[1], s[2], s[3], function() {\n tempElement.appendTo(form);\n form.submit();\n });\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n });\n\n // Confirmation for bulk tag combine button.\n $(\"#tag-management-combine\").click(function(e) {\n var pendingPromise = new Pending('core/tag:tag-management-combine');\n\n e.preventDefault();\n var form = $(this).closest('form').get(0);\n var tags = $(form).find(\"input[data-togglegroup='tags-manage'][data-toggle='slave']:checked\");\n\n if (tags.length <= 1) {\n str.get_strings([\n {key: 'combineselected', component: 'tag'},\n {key: 'selectmultipletags', component: 'tag'},\n {key: 'ok'},\n ])\n .then(function(s) {\n return notification.alert(s[0], s[1], s[2]);\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n\n return;\n }\n\n var tempElement = $(\"\").attr('name', this.name);\n var saveButtonText = '';\n var tagOptions = [];\n tags.each(function() {\n var tagid = $(this).val(),\n tagname = $('.inplaceeditable[data-itemtype=tagname][data-itemid=' + tagid + ']').attr('data-value');\n tagOptions.push({\n id: tagid,\n name: tagname\n });\n });\n\n str.get_strings([\n {key: 'combineselected', component: 'tag'},\n {key: 'continue', component: 'core'}\n ])\n .then(function(langStrings) {\n var modalTitle = langStrings[0];\n saveButtonText = langStrings[1];\n var templateContext = {\n tags: tagOptions\n };\n return SaveCancelModal.create({\n title: modalTitle,\n body: templates.render('core_tag/combine_tags', templateContext),\n buttons: {\n save: saveButtonText,\n },\n show: true,\n removeOnClose: true,\n });\n })\n .then(function(modal) {\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function(e) {\n e.preventDefault();\n\n // Append this temp element in the form in the tags list, not the form in the modal. Confusing, right?!?\n tempElement.appendTo(form);\n // Get the selected tag from the modal.\n var maintag = $('input[name=maintag]:checked', '#combinetags_form').val();\n // Append this in the tags list form.\n $(\"\").attr('name', 'maintag').attr('value', maintag).appendTo(form);\n // Submit the tags list form.\n form.submit();\n });\n\n // Tick the first option.\n $('#combinetags_form input[type=radio]').first().focus().prop('checked', true);\n\n return;\n\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n });\n\n // When user changes tag name to some name that already exists suggest to combine the tags.\n $('body').on('updatefailed', '[data-inplaceeditable][data-itemtype=tagname]', function(e) {\n var exception = e.exception; // The exception object returned by the callback.\n var newvalue = e.newvalue; // The value that user tried to udpated the element to.\n var tagid = $(e.target).attr('data-itemid');\n if (exception.errorcode === 'namesalreadybeeingused') {\n var pendingPromise = new Pending('core/tag:updatefailed');\n\n e.preventDefault(); // This will prevent default error dialogue.\n str.get_strings([\n {key: 'confirm', component: 'core'},\n {key: 'nameuseddocombine', component: 'tag'},\n {key: 'yes', component: 'core'},\n {key: 'cancel', component: 'core'},\n ])\n .then(function(s) {\n return notification.confirm(s[0], s[1], s[2], s[3], function() {\n window.location.href = window.location.href + \"&newname=\" + encodeURIComponent(newvalue) +\n \"&tagid=\" + encodeURIComponent(tagid) +\n '&action=renamecombine&sesskey=' + M.cfg.sesskey;\n });\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n }\n });\n\n // Form for adding standard tags.\n $('body').on('click', 'a[data-action=addstandardtag]', function(e) {\n var pendingPromise = new Pending('core/tag:addstandardtag');\n e.preventDefault();\n\n return SaveCancelModal.create({\n title: str.get_string('addotags', 'tag'),\n body: templates.render('core_tag/add_tags', {\n actionurl: window.location.href,\n sesskey: M.cfg.sesskey\n }),\n buttons: {\n save: str.get_string('continue', 'core'),\n },\n show: true,\n removeOnClose: true,\n })\n .then(function(modal) {\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function(e) {\n var tagsInput = $(e.currentTarget).find('#id_tagslist');\n var name = tagsInput.val().trim();\n\n // Set the text field's value to the trimmed value.\n tagsInput.val(name);\n\n // Add submit event listener to the form.\n var tagsForm = $('#addtags_form');\n tagsForm.on('submit', function(e) {\n // Validate the form.\n var form = $('#addtags_form');\n if (form[0].checkValidity() === false) {\n e.preventDefault();\n e.stopPropagation();\n }\n form.addClass('was-validated');\n\n // BS2 compatibility.\n $('[data-region=\"tagslistinput\"]').addClass('error');\n var errorMessage = $('#id_tagslist_error_message');\n errorMessage.removeAttr('hidden');\n errorMessage.addClass('help-block');\n });\n\n // Try to submit the form.\n tagsForm.submit();\n\n return false;\n });\n\n return;\n\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n });\n },\n\n /**\n * Initialises tag collection management page.\n *\n * @method initManageCollectionsPage\n */\n initManageCollectionsPage: function() {\n $('body').on('updated', '[data-inplaceeditable]', function(e) {\n var pendingPromise = new Pending('core/tag:initManageCollectionsPage-updated');\n\n var ajaxreturn = e.ajaxreturn,\n areaid, collid, isenabled;\n if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {\n areaid = $(this).attr('data-itemid');\n $(\".tag-collections-table ul[data-collectionid] li[data-areaid=\" + areaid + \"]\").hide();\n isenabled = ajaxreturn.value;\n if (isenabled === '1') {\n $(this).closest('tr').removeClass('dimmed_text');\n collid = $(this).closest('tr').find('[data-itemtype=\"tagareacollection\"]').attr(\"data-value\");\n $(\".tag-collections-table ul[data-collectionid=\" + collid + \"] li[data-areaid=\" + areaid + \"]\").show();\n } else {\n $(this).closest('tr').addClass('dimmed_text');\n }\n }\n if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareacollection') {\n areaid = $(this).attr('data-itemid');\n $(\".tag-collections-table ul[data-collectionid] li[data-areaid=\" + areaid + \"]\").hide();\n collid = $(this).attr('data-value');\n isenabled = $(this).closest('tr').find('[data-itemtype=\"tagareaenable\"]').attr(\"data-value\");\n if (isenabled === \"1\") {\n $(\".tag-collections-table ul[data-collectionid=\" + collid + \"] li[data-areaid=\" + areaid + \"]\").show();\n }\n }\n\n pendingPromise.resolve();\n });\n\n $('body').on('click', '.addtagcoll > a', function(e) {\n var pendingPromise = new Pending('core/tag:initManageCollectionsPage-addtagcoll');\n\n e.preventDefault();\n var keys = [\n {\n key: 'addtagcoll',\n component: 'tag'\n },\n {\n key: 'create',\n component: 'core'\n }\n ];\n\n var href = $(this).attr('data-url');\n var saveButtonText = '';\n str.get_strings(keys)\n .then(function(langStrings) {\n var modalTitle = langStrings[0];\n saveButtonText = langStrings[1];\n var templateContext = {\n actionurl: href,\n sesskey: M.cfg.sesskey\n };\n return SaveCancelModal.create({\n title: modalTitle,\n body: templates.render('core_tag/add_tag_collection', templateContext),\n buttons: {\n save: saveButtonText,\n },\n show: true,\n removeOnClose: true,\n });\n })\n .then(function(modal) {\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function(e) {\n var collectionInput = $(e.currentTarget).find('#addtagcoll_name');\n var name = collectionInput.val().trim();\n // Set the text field's value to the trimmed value.\n collectionInput.val(name);\n\n // Add submit event listener to the form.\n var form = $('#addtagcoll_form');\n form.on('submit', function(e) {\n // Validate the form.\n if (form[0].checkValidity() === false) {\n e.preventDefault();\n e.stopPropagation();\n }\n form.addClass('was-validated');\n\n // BS2 compatibility.\n $('[data-region=\"addtagcoll_nameinput\"]').addClass('error');\n var errorMessage = $('#id_addtagcoll_name_error_message');\n errorMessage.removeAttr('hidden');\n errorMessage.addClass('help-block');\n });\n\n // Try to submit the form.\n form.submit();\n\n return false;\n });\n\n return modal;\n\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n });\n\n $('body').on('click', '.tag-collections-table .action_delete', function(e) {\n var pendingPromise = new Pending('core/tag:initManageCollectionsPage-action_delete');\n\n e.preventDefault();\n var href = $(this).attr('data-url') + '&sesskey=' + M.cfg.sesskey;\n str.get_strings([\n {key: 'delete'},\n {key: 'suredeletecoll', component: 'tag', param: $(this).attr('data-collname')},\n {key: 'yes'},\n {key: 'no'},\n ])\n .then(function(s) {\n return notification.confirm(s[0], s[1], s[2], s[3], function() {\n window.location.href = href;\n });\n })\n .always(pendingPromise.resolve)\n .catch(notification.exception);\n });\n }\n };\n});\n"],"names":["define","$","ajax","templates","notification","str","SaveCancelModal","ModalEvents","Pending","initTagindexPage","delegate","e","pendingPromise","preventDefault","target","this","query","search","replace","tagarea","closest","args","split","reduce","s","c","t","decodeURIComponent","call","methodname","tagindex","then","data","render","html","js","replaceNode","always","resolve","catch","exception","initManagePage","on","get_strings","key","component","result","ajaxreturn","itemid","find","itemtype","row","value","removeClass","addClass","href","attr","confirm","window","location","click","form","get","length","tempElement","name","appendTo","submit","tags","alert","saveButtonText","tagOptions","each","tagid","val","tagname","push","id","langStrings","modalTitle","templateContext","create","title","body","buttons","save","show","removeOnClose","modal","getRoot","maintag","first","focus","prop","newvalue","errorcode","encodeURIComponent","M","cfg","sesskey","get_string","actionurl","tagsInput","currentTarget","trim","tagsForm","checkValidity","stopPropagation","errorMessage","removeAttr","initManageCollectionsPage","areaid","collid","hide","collectionInput","param"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"tag.min.js","sources":["../src/tag.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 * AJAX helper for the tag management page.\n *\n * @module core/tag\n * @copyright 2015 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.0\n */\n\nimport $ from 'jquery';\nimport {call as fetchMany} from 'core/ajax';\nimport * as Notification from 'core/notification';\nimport * as Templates from 'core/templates';\nimport {\n get_string as getString,\n get_strings as getStrings,\n} from 'core/str';\nimport * as ModalEvents from 'core/modal_events';\nimport Pending from 'core/pending';\nimport SaveCancelModal from 'core/modal_save_cancel';\nimport Config from 'core/config';\n\nconst getTagIndex = (tagindex) => fetchMany([{\n methodname: 'core_tag_get_tagindex',\n args: {tagindex}\n}])[0];\n\nconst getCheckedTags = (form) => form.querySelectorAll('input[data-togglegroup=\"tags-manage\"][data-toggle=\"slave\"]:checked');\n\nconst handleCombineRequest = async(tagManagementCombine) => {\n const pendingPromise = new Pending('core/tag:tag-management-combine');\n const form = tagManagementCombine.closest('form');\n const checkedTags = getCheckedTags(form);\n\n if (checkedTags.length <= 1) {\n // We need at least 2 tags to combine them.\n Notification.alert(\n getString('combineselected', 'tag'),\n getString('selectmultipletags', 'tag'),\n getString('ok'),\n );\n\n return;\n }\n\n const tags = Array.from(checkedTags.values()).map((tag) => {\n const namedElement = document.querySelector(`.inplaceeditable[data-itemtype=tagname][data-itemid=\"${tag.value}\"]`);\n return {\n id: tag.value,\n name: namedElement.dataset.value,\n };\n });\n\n const modal = await SaveCancelModal.create({\n title: getString('combineselected', 'tag'),\n buttons: {\n save: getString('continue', 'core'),\n },\n body: Templates.render('core_tag/combine_tags', {tags}),\n show: true,\n removeOnClose: true,\n });\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, (e) => {\n e.preventDefault();\n\n // Append this temp element in the form in the tags list, not the form in the modal. Confusing, right?!?\n const tempElement = document.createElement('input');\n tempElement.hidden = true;\n tempElement.name = tagManagementCombine.name;\n form.append(tempElement);\n\n // Get the selected tag from the modal.\n var maintag = $('input[name=maintag]:checked', '#combinetags_form').val();\n // Append this in the tags list form.\n $(\"\").attr('name', 'maintag').attr('value', maintag).appendTo(form);\n // Submit the tags list form.\n form.submit();\n });\n\n await modal.getBodyPromise();\n // Tick the first option.\n const firstOption = document.querySelector('#combinetags_form input[type=radio]');\n firstOption.focus();\n firstOption.checked = true;\n\n pendingPromise.resolve();\n\n return;\n};\n\nconst addStandardTags = async() => {\n var pendingPromise = new Pending('core/tag:addstandardtag');\n\n const modal = await SaveCancelModal.create({\n title: getString('addotags', 'tag'),\n body: Templates.render('core_tag/add_tags', {\n actionurl: window.location.href,\n sesskey: M.cfg.sesskey,\n }),\n buttons: {\n save: getString('continue', 'core'),\n },\n removeOnClose: true,\n show: true,\n });\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, (e) => {\n var tagsInput = $(e.currentTarget).find('#id_tagslist');\n var name = tagsInput.val().trim();\n\n // Set the text field's value to the trimmed value.\n tagsInput.val(name);\n\n // Add submit event listener to the form.\n var tagsForm = $('#addtags_form');\n tagsForm.on('submit', function(e) {\n // Validate the form.\n var form = $('#addtags_form');\n if (form[0].checkValidity() === false) {\n e.preventDefault();\n e.stopPropagation();\n }\n form.addClass('was-validated');\n\n // BS2 compatibility.\n $('[data-region=\"tagslistinput\"]').addClass('error');\n var errorMessage = $('#id_tagslist_error_message');\n errorMessage.removeAttr('hidden');\n errorMessage.addClass('help-block');\n });\n\n // Try to submit the form.\n tagsForm.submit();\n\n return false;\n });\n\n await modal.getBodyPromise();\n pendingPromise.resolve();\n};\n\nconst deleteSelectedTags = async(form) => {\n const checkedTags = getCheckedTags(form);\n if (!checkedTags.length) {\n return;\n }\n\n try {\n await Notification.saveCancelPromise(\n getString('delete'),\n getString('confirmdeletetags', 'tag'),\n getString('yes'),\n getString('no'),\n );\n\n // Append this temp element in the form in the tags list, not the form in the modal. Confusing, right?!?\n const tempElement = document.createElement('input');\n tempElement.hidden = true;\n tempElement.name = 'bulkdelete';\n form.append(tempElement);\n form.submit();\n } catch {\n return;\n }\n};\n\nconst deleteSelectedTag = async(button) => {\n try {\n await Notification.saveCancelPromise(\n getString('delete'),\n getString('confirmdeletetag', 'tag'),\n getString('yes'),\n getString('no'),\n );\n\n window.location.href = button.href;\n } catch {\n return;\n }\n};\n\nconst deleteSelectedCollection = async(button) => {\n try {\n await Notification.saveCancelPromise(\n getString('delete'),\n getString('suredeletecoll', 'tag', button.dataset.collname),\n getString('yes'),\n getString('no'),\n );\n\n const redirectTarget = new URL(button.dataset.url);\n redirectTarget.searchParams.set('sesskey', Config.sesskey);\n window.location.href = redirectTarget;\n } catch {\n return;\n }\n};\n\nconst addTagCollection = async(link) => {\n const pendingPromise = new Pending('core/tag:initManageCollectionsPage-addtagcoll');\n const href = link.dataset.url;\n\n const modal = await SaveCancelModal.create({\n title: getString('addtagcoll', 'tag'),\n buttons: {\n save: getString('create', 'core'),\n },\n body: Templates.render('core_tag/add_tag_collection', {\n actionurl: href,\n sesskey: M.cfg.sesskey,\n }),\n removeOnClose: true,\n show: true,\n });\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, (e) => {\n const collectionInput = $(e.currentTarget).find('#addtagcoll_name');\n const name = collectionInput.val().trim();\n // Set the text field's value to the trimmed value.\n collectionInput.val(name);\n\n // Add submit event listener to the form.\n const form = $('#addtagcoll_form');\n form.on('submit', function(e) {\n // Validate the form.\n if (form[0].checkValidity() === false) {\n e.preventDefault();\n e.stopPropagation();\n }\n form.addClass('was-validated');\n\n // BS2 compatibility.\n $('[data-region=\"addtagcoll_nameinput\"]').addClass('error');\n const errorMessage = $('#id_addtagcoll_name_error_message');\n errorMessage.removeAttr('hidden');\n errorMessage.addClass('help-block');\n });\n\n // Try to submit the form.\n form.submit();\n\n return false;\n });\n\n pendingPromise.resolve();\n};\n\n/**\n * Initialises tag index page.\n *\n * @method initTagindexPage\n */\nexport const initTagindexPage = async() => {\n document.addEventListener('click', async(e) => {\n const targetArea = e.target.closest('a[data-quickload=\"1\"]');\n if (!targetArea) {\n return;\n }\n const tagArea = targetArea.closest('.tagarea[data-ta]');\n if (!tagArea) {\n return;\n }\n\n e.preventDefault();\n const pendingPromise = new Pending('core/tag:initTagindexPage');\n\n const query = targetArea.search.replace(/^\\?/, '');\n const params = Object.fromEntries((new URLSearchParams(query)).entries());\n\n try {\n const data = await getTagIndex(params);\n const {html, js} = await Templates.renderForPromise('core_tag/index', data);\n Templates.replaceNode(tagArea, html, js);\n } catch (error) {\n Notification.exception(error);\n }\n pendingPromise.resolve();\n });\n};\n\n/**\n * Initialises tag management page.\n *\n * @method initManagePage\n */\nexport const initManagePage = () => {\n // Set cell 'time modified' to 'now' when any of the element is updated in this row.\n $('body').on('updated', '[data-inplaceeditable]', function(e) {\n var pendingPromise = new Pending('core/tag:initManagePage');\n\n getStrings([\n {\n key: 'selecttag',\n component: 'core_tag',\n },\n {\n key: 'now',\n component: 'core',\n },\n ])\n .then(function(result) {\n $('label[for=\"tagselect' + e.ajaxreturn.itemid + '\"]').html(result[0]);\n $(e.target).closest('tr').find('td.col-timemodified').html(result[1]);\n\n return;\n })\n .always(pendingPromise.resolve)\n .catch(Notification.exception);\n\n if (e.ajaxreturn.itemtype === 'tagflag') {\n var row = $(e.target).closest('tr');\n if (e.ajaxreturn.value === '0') {\n row.removeClass('table-warning');\n } else {\n row.addClass('table-warning');\n }\n }\n });\n\n // Confirmation for bulk tag combine button.\n document.addEventListener('click', async(e) => {\n const tagManagementCombine = e.target.closest('#tag-management-combine');\n if (tagManagementCombine) {\n e.preventDefault();\n handleCombineRequest(tagManagementCombine);\n }\n\n if (e.target.closest('a[data-action=\"addstandardtag\"]')) {\n e.preventDefault();\n addStandardTags();\n }\n\n const bulkActionDeleteButton = e.target.closest('#tag-management-delete');\n if (bulkActionDeleteButton) {\n e.preventDefault();\n deleteSelectedTags(bulkActionDeleteButton.closest('form'));\n }\n\n const rowDeleteButton = e.target.closest('.tagdelete');\n if (rowDeleteButton) {\n e.preventDefault();\n deleteSelectedTag(rowDeleteButton);\n }\n });\n\n // When user changes tag name to some name that already exists suggest to combine the tags.\n $('body').on('updatefailed', '[data-inplaceeditable][data-itemtype=tagname]', async(e) => {\n var exception = e.exception; // The exception object returned by the callback.\n var newvalue = e.newvalue; // The value that user tried to udpated the element to.\n var tagid = $(e.target).attr('data-itemid');\n if (exception.errorcode !== 'namesalreadybeeingused') {\n return;\n }\n e.preventDefault(); // This will prevent default error dialogue.\n\n try {\n await Notification.saveCancelPromise(\n getString('confirm'),\n getString('nameuseddocombine', 'tag'),\n getString('yes'),\n getString('cancel'),\n );\n\n // The Promise will resolve on 'Yes' button, and reject on 'Cancel' button.\n const redirectTarget = new URL(window.location);\n redirectTarget.searchParams.set('newname', newvalue);\n redirectTarget.searchParams.set('tagid', tagid);\n redirectTarget.searchParams.set('action', 'renamecombine');\n redirectTarget.searchParams.set('sesskey', Config.sesskey);\n\n window.location.href = redirectTarget;\n } catch {\n return;\n }\n });\n};\n\n/**\n * Initialises tag collection management page.\n *\n * @method initManageCollectionsPage\n */\nexport const initManageCollectionsPage = () => {\n $('body').on('updated', '[data-inplaceeditable]', function(e) {\n var pendingPromise = new Pending('core/tag:initManageCollectionsPage-updated');\n\n var ajaxreturn = e.ajaxreturn,\n areaid, collid, isenabled;\n if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {\n areaid = $(this).attr('data-itemid');\n $(\".tag-collections-table ul[data-collectionid] li[data-areaid=\" + areaid + \"]\").hide();\n isenabled = ajaxreturn.value;\n if (isenabled === '1') {\n $(this).closest('tr').removeClass('dimmed_text');\n collid = $(this).closest('tr').find('[data-itemtype=\"tagareacollection\"]').attr(\"data-value\");\n $(\".tag-collections-table ul[data-collectionid=\" + collid + \"] li[data-areaid=\" + areaid + \"]\").show();\n } else {\n $(this).closest('tr').addClass('dimmed_text');\n }\n }\n if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareacollection') {\n areaid = $(this).attr('data-itemid');\n $(\".tag-collections-table ul[data-collectionid] li[data-areaid=\" + areaid + \"]\").hide();\n collid = $(this).attr('data-value');\n isenabled = $(this).closest('tr').find('[data-itemtype=\"tagareaenable\"]').attr(\"data-value\");\n if (isenabled === \"1\") {\n $(\".tag-collections-table ul[data-collectionid=\" + collid + \"] li[data-areaid=\" + areaid + \"]\").show();\n }\n }\n\n pendingPromise.resolve();\n });\n\n document.addEventListener('click', async(e) => {\n const addTagCollectionNode = e.target.closest('.addtagcoll > a');\n if (addTagCollectionNode) {\n e.preventDefault();\n addTagCollection(addTagCollectionNode);\n return;\n }\n\n const deleteCollectionButton = e.target.closest('.tag-collections-table .action_delete');\n if (deleteCollectionButton) {\n e.preventDefault();\n deleteSelectedCollection(deleteCollectionButton);\n }\n });\n};\n"],"names":["getCheckedTags","form","querySelectorAll","async","document","addEventListener","targetArea","e","target","closest","tagArea","preventDefault","pendingPromise","Pending","query","search","replace","params","Object","fromEntries","URLSearchParams","entries","data","tagindex","methodname","args","html","js","Templates","renderForPromise","replaceNode","error","Notification","exception","resolve","on","key","component","then","result","ajaxreturn","itemid","find","always","catch","itemtype","row","value","removeClass","addClass","tagManagementCombine","checkedTags","length","alert","tags","Array","from","values","map","tag","namedElement","querySelector","id","name","dataset","modal","SaveCancelModal","create","title","buttons","save","body","render","show","removeOnClose","getRoot","ModalEvents","tempElement","createElement","hidden","append","maintag","val","attr","appendTo","submit","getBodyPromise","firstOption","focus","checked","handleCombineRequest","actionurl","window","location","href","sesskey","M","cfg","tagsInput","currentTarget","trim","tagsForm","checkValidity","stopPropagation","errorMessage","removeAttr","addStandardTags","bulkActionDeleteButton","saveCancelPromise","deleteSelectedTags","rowDeleteButton","button","deleteSelectedTag","newvalue","tagid","errorcode","redirectTarget","URL","searchParams","set","Config","areaid","collid","this","hide","addTagCollectionNode","link","url","collectionInput","addTagCollection","deleteCollectionButton","collname","deleteSelectedCollection"],"mappings":"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"}
\ No newline at end of file
diff --git a/lib/amd/src/tag.js b/lib/amd/src/tag.js
index 02b65aab4ed..042bcdcb4b5 100644
--- a/lib/amd/src/tag.js
+++ b/lib/amd/src/tag.js
@@ -21,445 +21,427 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.0
*/
-define([
- 'jquery',
- 'core/ajax',
- 'core/templates',
- 'core/notification',
- 'core/str',
- 'core/modal_save_cancel',
- 'core/modal_events',
- 'core/pending',
-], function(
- $,
- ajax,
- templates,
- notification,
- str,
- SaveCancelModal,
- ModalEvents,
- Pending
-) {
- return /** @alias module:core/tag */ {
- /**
- * Initialises tag index page.
- *
- * @method initTagindexPage
- */
- initTagindexPage: function() {
- // Click handler for changing tag type.
- $('body').delegate('.tagarea[data-ta] a[data-quickload=1]', 'click', function(e) {
- var pendingPromise = new Pending('core/tag:initTagindexPage');
+import $ from 'jquery';
+import {call as fetchMany} from 'core/ajax';
+import * as Notification from 'core/notification';
+import * as Templates from 'core/templates';
+import {
+ get_string as getString,
+ get_strings as getStrings,
+} from 'core/str';
+import * as ModalEvents from 'core/modal_events';
+import Pending from 'core/pending';
+import SaveCancelModal from 'core/modal_save_cancel';
+import Config from 'core/config';
- e.preventDefault();
- var target = $(this);
- var query = target[0].search.replace(/^\?/, '');
- var tagarea = target.closest('.tagarea[data-ta]');
- var args = query.split('&').reduce(function(s, c) {
- var t = c.split('=');
- s[t[0]] = decodeURIComponent(t[1]);
- return s;
- }, {});
+const getTagIndex = (tagindex) => fetchMany([{
+ methodname: 'core_tag_get_tagindex',
+ args: {tagindex}
+}])[0];
- ajax.call([{
- methodname: 'core_tag_get_tagindex',
- args: {tagindex: args}
- }])[0]
- .then(function(data) {
- return templates.render('core_tag/index', data);
- })
- .then(function(html, js) {
- templates.replaceNode(tagarea, html, js);
- return;
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- });
+const getCheckedTags = (form) => form.querySelectorAll('input[data-togglegroup="tags-manage"][data-toggle="slave"]:checked');
+
+const handleCombineRequest = async(tagManagementCombine) => {
+ const pendingPromise = new Pending('core/tag:tag-management-combine');
+ const form = tagManagementCombine.closest('form');
+ const checkedTags = getCheckedTags(form);
+
+ if (checkedTags.length <= 1) {
+ // We need at least 2 tags to combine them.
+ Notification.alert(
+ getString('combineselected', 'tag'),
+ getString('selectmultipletags', 'tag'),
+ getString('ok'),
+ );
+
+ return;
+ }
+
+ const tags = Array.from(checkedTags.values()).map((tag) => {
+ const namedElement = document.querySelector(`.inplaceeditable[data-itemtype=tagname][data-itemid="${tag.value}"]`);
+ return {
+ id: tag.value,
+ name: namedElement.dataset.value,
+ };
+ });
+
+ const modal = await SaveCancelModal.create({
+ title: getString('combineselected', 'tag'),
+ buttons: {
+ save: getString('continue', 'core'),
},
+ body: Templates.render('core_tag/combine_tags', {tags}),
+ show: true,
+ removeOnClose: true,
+ });
- /**
- * Initialises tag management page.
- *
- * @method initManagePage
- */
- initManagePage: function() {
- // Set cell 'time modified' to 'now' when any of the element is updated in this row.
- $('body').on('updated', '[data-inplaceeditable]', function(e) {
- var pendingPromise = new Pending('core/tag:initManagePage');
+ // Handle save event.
+ modal.getRoot().on(ModalEvents.save, (e) => {
+ e.preventDefault();
- str.get_strings([
- {
- key: 'selecttag',
- component: 'core_tag',
- },
- {
- key: 'now',
- component: 'core',
- },
- ])
- .then(function(result) {
- $('label[for="tagselect' + e.ajaxreturn.itemid + '"]').html(result[0]);
- $(e.target).closest('tr').find('td.col-timemodified').html(result[1]);
+ // Append this temp element in the form in the tags list, not the form in the modal. Confusing, right?!?
+ const tempElement = document.createElement('input');
+ tempElement.hidden = true;
+ tempElement.name = tagManagementCombine.name;
+ form.append(tempElement);
- return;
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
+ // Get the selected tag from the modal.
+ var maintag = $('input[name=maintag]:checked', '#combinetags_form').val();
+ // Append this in the tags list form.
+ $("").attr('name', 'maintag').attr('value', maintag).appendTo(form);
+ // Submit the tags list form.
+ form.submit();
+ });
- if (e.ajaxreturn.itemtype === 'tagflag') {
- var row = $(e.target).closest('tr');
- if (e.ajaxreturn.value === '0') {
- row.removeClass('table-warning');
- } else {
- row.addClass('table-warning');
- }
- }
- });
+ await modal.getBodyPromise();
+ // Tick the first option.
+ const firstOption = document.querySelector('#combinetags_form input[type=radio]');
+ firstOption.focus();
+ firstOption.checked = true;
- // Confirmation for single tag delete link.
- $('.tag-management-table').delegate('a.tagdelete', 'click', function(e) {
- var pendingPromise = new Pending('core/tag:tagdelete');
+ pendingPromise.resolve();
- e.preventDefault();
- var href = $(this).attr('href');
- str.get_strings([
- {key: 'delete', component: 'core'},
- {key: 'confirmdeletetag', component: 'tag'},
- {key: 'yes', component: 'core'},
- {key: 'no', component: 'core'},
- ])
- .then(function(s) {
- return notification.confirm(s[0], s[1], s[2], s[3], function() {
- window.location.href = href;
- });
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- });
+ return;
+};
- // Confirmation for bulk tag delete button.
- $("#tag-management-delete").click(function(e) {
- var form = $(this).closest('form').get(0);
+const addStandardTags = async() => {
+ var pendingPromise = new Pending('core/tag:addstandardtag');
- var cnt = $(form).find("input[data-togglegroup='tags-manage'][data-toggle='slave']:checked").length;
- if (!cnt) {
- return;
- }
-
- var pendingPromise = new Pending('core/tag:tag-management-delete');
- var tempElement = $("").attr('name', this.name);
- e.preventDefault();
- str.get_strings([
- {key: 'delete', component: 'core'},
- {key: 'confirmdeletetags', component: 'tag'},
- {key: 'yes', component: 'core'},
- {key: 'no', component: 'core'},
- ])
- .then(function(s) {
- return notification.confirm(s[0], s[1], s[2], s[3], function() {
- tempElement.appendTo(form);
- form.submit();
- });
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- });
-
- // Confirmation for bulk tag combine button.
- $("#tag-management-combine").click(function(e) {
- var pendingPromise = new Pending('core/tag:tag-management-combine');
-
- e.preventDefault();
- var form = $(this).closest('form').get(0);
- var tags = $(form).find("input[data-togglegroup='tags-manage'][data-toggle='slave']:checked");
-
- if (tags.length <= 1) {
- str.get_strings([
- {key: 'combineselected', component: 'tag'},
- {key: 'selectmultipletags', component: 'tag'},
- {key: 'ok'},
- ])
- .then(function(s) {
- return notification.alert(s[0], s[1], s[2]);
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
-
- return;
- }
-
- var tempElement = $("").attr('name', this.name);
- var saveButtonText = '';
- var tagOptions = [];
- tags.each(function() {
- var tagid = $(this).val(),
- tagname = $('.inplaceeditable[data-itemtype=tagname][data-itemid=' + tagid + ']').attr('data-value');
- tagOptions.push({
- id: tagid,
- name: tagname
- });
- });
-
- str.get_strings([
- {key: 'combineselected', component: 'tag'},
- {key: 'continue', component: 'core'}
- ])
- .then(function(langStrings) {
- var modalTitle = langStrings[0];
- saveButtonText = langStrings[1];
- var templateContext = {
- tags: tagOptions
- };
- return SaveCancelModal.create({
- title: modalTitle,
- body: templates.render('core_tag/combine_tags', templateContext),
- buttons: {
- save: saveButtonText,
- },
- show: true,
- removeOnClose: true,
- });
- })
- .then(function(modal) {
-
- // Handle save event.
- modal.getRoot().on(ModalEvents.save, function(e) {
- e.preventDefault();
-
- // Append this temp element in the form in the tags list, not the form in the modal. Confusing, right?!?
- tempElement.appendTo(form);
- // Get the selected tag from the modal.
- var maintag = $('input[name=maintag]:checked', '#combinetags_form').val();
- // Append this in the tags list form.
- $("").attr('name', 'maintag').attr('value', maintag).appendTo(form);
- // Submit the tags list form.
- form.submit();
- });
-
- // Tick the first option.
- $('#combinetags_form input[type=radio]').first().focus().prop('checked', true);
-
- return;
-
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- });
-
- // When user changes tag name to some name that already exists suggest to combine the tags.
- $('body').on('updatefailed', '[data-inplaceeditable][data-itemtype=tagname]', function(e) {
- var exception = e.exception; // The exception object returned by the callback.
- var newvalue = e.newvalue; // The value that user tried to udpated the element to.
- var tagid = $(e.target).attr('data-itemid');
- if (exception.errorcode === 'namesalreadybeeingused') {
- var pendingPromise = new Pending('core/tag:updatefailed');
-
- e.preventDefault(); // This will prevent default error dialogue.
- str.get_strings([
- {key: 'confirm', component: 'core'},
- {key: 'nameuseddocombine', component: 'tag'},
- {key: 'yes', component: 'core'},
- {key: 'cancel', component: 'core'},
- ])
- .then(function(s) {
- return notification.confirm(s[0], s[1], s[2], s[3], function() {
- window.location.href = window.location.href + "&newname=" + encodeURIComponent(newvalue) +
- "&tagid=" + encodeURIComponent(tagid) +
- '&action=renamecombine&sesskey=' + M.cfg.sesskey;
- });
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- }
- });
-
- // Form for adding standard tags.
- $('body').on('click', 'a[data-action=addstandardtag]', function(e) {
- var pendingPromise = new Pending('core/tag:addstandardtag');
- e.preventDefault();
-
- return SaveCancelModal.create({
- title: str.get_string('addotags', 'tag'),
- body: templates.render('core_tag/add_tags', {
- actionurl: window.location.href,
- sesskey: M.cfg.sesskey
- }),
- buttons: {
- save: str.get_string('continue', 'core'),
- },
- show: true,
- removeOnClose: true,
- })
- .then(function(modal) {
- // Handle save event.
- modal.getRoot().on(ModalEvents.save, function(e) {
- var tagsInput = $(e.currentTarget).find('#id_tagslist');
- var name = tagsInput.val().trim();
-
- // Set the text field's value to the trimmed value.
- tagsInput.val(name);
-
- // Add submit event listener to the form.
- var tagsForm = $('#addtags_form');
- tagsForm.on('submit', function(e) {
- // Validate the form.
- var form = $('#addtags_form');
- if (form[0].checkValidity() === false) {
- e.preventDefault();
- e.stopPropagation();
- }
- form.addClass('was-validated');
-
- // BS2 compatibility.
- $('[data-region="tagslistinput"]').addClass('error');
- var errorMessage = $('#id_tagslist_error_message');
- errorMessage.removeAttr('hidden');
- errorMessage.addClass('help-block');
- });
-
- // Try to submit the form.
- tagsForm.submit();
-
- return false;
- });
-
- return;
-
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- });
+ const modal = await SaveCancelModal.create({
+ title: getString('addotags', 'tag'),
+ body: Templates.render('core_tag/add_tags', {
+ actionurl: window.location.href,
+ sesskey: M.cfg.sesskey,
+ }),
+ buttons: {
+ save: getString('continue', 'core'),
},
+ removeOnClose: true,
+ show: true,
+ });
- /**
- * Initialises tag collection management page.
- *
- * @method initManageCollectionsPage
- */
- initManageCollectionsPage: function() {
- $('body').on('updated', '[data-inplaceeditable]', function(e) {
- var pendingPromise = new Pending('core/tag:initManageCollectionsPage-updated');
+ // Handle save event.
+ modal.getRoot().on(ModalEvents.save, (e) => {
+ var tagsInput = $(e.currentTarget).find('#id_tagslist');
+ var name = tagsInput.val().trim();
- var ajaxreturn = e.ajaxreturn,
- areaid, collid, isenabled;
- if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {
- areaid = $(this).attr('data-itemid');
- $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
- isenabled = ajaxreturn.value;
- if (isenabled === '1') {
- $(this).closest('tr').removeClass('dimmed_text');
- collid = $(this).closest('tr').find('[data-itemtype="tagareacollection"]').attr("data-value");
- $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
- } else {
- $(this).closest('tr').addClass('dimmed_text');
- }
- }
- if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareacollection') {
- areaid = $(this).attr('data-itemid');
- $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
- collid = $(this).attr('data-value');
- isenabled = $(this).closest('tr').find('[data-itemtype="tagareaenable"]').attr("data-value");
- if (isenabled === "1") {
- $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
- }
- }
-
- pendingPromise.resolve();
- });
-
- $('body').on('click', '.addtagcoll > a', function(e) {
- var pendingPromise = new Pending('core/tag:initManageCollectionsPage-addtagcoll');
+ // Set the text field's value to the trimmed value.
+ tagsInput.val(name);
+ // Add submit event listener to the form.
+ var tagsForm = $('#addtags_form');
+ tagsForm.on('submit', function(e) {
+ // Validate the form.
+ var form = $('#addtags_form');
+ if (form[0].checkValidity() === false) {
e.preventDefault();
- var keys = [
- {
- key: 'addtagcoll',
- component: 'tag'
- },
- {
- key: 'create',
- component: 'core'
- }
- ];
+ e.stopPropagation();
+ }
+ form.addClass('was-validated');
- var href = $(this).attr('data-url');
- var saveButtonText = '';
- str.get_strings(keys)
- .then(function(langStrings) {
- var modalTitle = langStrings[0];
- saveButtonText = langStrings[1];
- var templateContext = {
- actionurl: href,
- sesskey: M.cfg.sesskey
- };
- return SaveCancelModal.create({
- title: modalTitle,
- body: templates.render('core_tag/add_tag_collection', templateContext),
- buttons: {
- save: saveButtonText,
- },
- show: true,
- removeOnClose: true,
- });
- })
- .then(function(modal) {
- // Handle save event.
- modal.getRoot().on(ModalEvents.save, function(e) {
- var collectionInput = $(e.currentTarget).find('#addtagcoll_name');
- var name = collectionInput.val().trim();
- // Set the text field's value to the trimmed value.
- collectionInput.val(name);
+ // BS2 compatibility.
+ $('[data-region="tagslistinput"]').addClass('error');
+ var errorMessage = $('#id_tagslist_error_message');
+ errorMessage.removeAttr('hidden');
+ errorMessage.addClass('help-block');
+ });
- // Add submit event listener to the form.
- var form = $('#addtagcoll_form');
- form.on('submit', function(e) {
- // Validate the form.
- if (form[0].checkValidity() === false) {
- e.preventDefault();
- e.stopPropagation();
- }
- form.addClass('was-validated');
+ // Try to submit the form.
+ tagsForm.submit();
- // BS2 compatibility.
- $('[data-region="addtagcoll_nameinput"]').addClass('error');
- var errorMessage = $('#id_addtagcoll_name_error_message');
- errorMessage.removeAttr('hidden');
- errorMessage.addClass('help-block');
- });
+ return false;
+ });
- // Try to submit the form.
- form.submit();
+ await modal.getBodyPromise();
+ pendingPromise.resolve();
+};
- return false;
- });
+const deleteSelectedTags = async(form) => {
+ const checkedTags = getCheckedTags(form);
+ if (!checkedTags.length) {
+ return;
+ }
- return modal;
+ try {
+ await Notification.saveCancelPromise(
+ getString('delete'),
+ getString('confirmdeletetags', 'tag'),
+ getString('yes'),
+ getString('no'),
+ );
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- });
+ // Append this temp element in the form in the tags list, not the form in the modal. Confusing, right?!?
+ const tempElement = document.createElement('input');
+ tempElement.hidden = true;
+ tempElement.name = 'bulkdelete';
+ form.append(tempElement);
+ form.submit();
+ } catch {
+ return;
+ }
+};
- $('body').on('click', '.tag-collections-table .action_delete', function(e) {
- var pendingPromise = new Pending('core/tag:initManageCollectionsPage-action_delete');
+const deleteSelectedTag = async(button) => {
+ try {
+ await Notification.saveCancelPromise(
+ getString('delete'),
+ getString('confirmdeletetag', 'tag'),
+ getString('yes'),
+ getString('no'),
+ );
+ window.location.href = button.href;
+ } catch {
+ return;
+ }
+};
+
+const deleteSelectedCollection = async(button) => {
+ try {
+ await Notification.saveCancelPromise(
+ getString('delete'),
+ getString('suredeletecoll', 'tag', button.dataset.collname),
+ getString('yes'),
+ getString('no'),
+ );
+
+ const redirectTarget = new URL(button.dataset.url);
+ redirectTarget.searchParams.set('sesskey', Config.sesskey);
+ window.location.href = redirectTarget;
+ } catch {
+ return;
+ }
+};
+
+const addTagCollection = async(link) => {
+ const pendingPromise = new Pending('core/tag:initManageCollectionsPage-addtagcoll');
+ const href = link.dataset.url;
+
+ const modal = await SaveCancelModal.create({
+ title: getString('addtagcoll', 'tag'),
+ buttons: {
+ save: getString('create', 'core'),
+ },
+ body: Templates.render('core_tag/add_tag_collection', {
+ actionurl: href,
+ sesskey: M.cfg.sesskey,
+ }),
+ removeOnClose: true,
+ show: true,
+ });
+
+ // Handle save event.
+ modal.getRoot().on(ModalEvents.save, (e) => {
+ const collectionInput = $(e.currentTarget).find('#addtagcoll_name');
+ const name = collectionInput.val().trim();
+ // Set the text field's value to the trimmed value.
+ collectionInput.val(name);
+
+ // Add submit event listener to the form.
+ const form = $('#addtagcoll_form');
+ form.on('submit', function(e) {
+ // Validate the form.
+ if (form[0].checkValidity() === false) {
e.preventDefault();
- var href = $(this).attr('data-url') + '&sesskey=' + M.cfg.sesskey;
- str.get_strings([
- {key: 'delete'},
- {key: 'suredeletecoll', component: 'tag', param: $(this).attr('data-collname')},
- {key: 'yes'},
- {key: 'no'},
- ])
- .then(function(s) {
- return notification.confirm(s[0], s[1], s[2], s[3], function() {
- window.location.href = href;
- });
- })
- .always(pendingPromise.resolve)
- .catch(notification.exception);
- });
+ e.stopPropagation();
+ }
+ form.addClass('was-validated');
+
+ // BS2 compatibility.
+ $('[data-region="addtagcoll_nameinput"]').addClass('error');
+ const errorMessage = $('#id_addtagcoll_name_error_message');
+ errorMessage.removeAttr('hidden');
+ errorMessage.addClass('help-block');
+ });
+
+ // Try to submit the form.
+ form.submit();
+
+ return false;
+ });
+
+ pendingPromise.resolve();
+};
+
+/**
+ * Initialises tag index page.
+ *
+ * @method initTagindexPage
+ */
+export const initTagindexPage = async() => {
+ document.addEventListener('click', async(e) => {
+ const targetArea = e.target.closest('a[data-quickload="1"]');
+ if (!targetArea) {
+ return;
}
- };
-});
+ const tagArea = targetArea.closest('.tagarea[data-ta]');
+ if (!tagArea) {
+ return;
+ }
+
+ e.preventDefault();
+ const pendingPromise = new Pending('core/tag:initTagindexPage');
+
+ const query = targetArea.search.replace(/^\?/, '');
+ const params = Object.fromEntries((new URLSearchParams(query)).entries());
+
+ try {
+ const data = await getTagIndex(params);
+ const {html, js} = await Templates.renderForPromise('core_tag/index', data);
+ Templates.replaceNode(tagArea, html, js);
+ } catch (error) {
+ Notification.exception(error);
+ }
+ pendingPromise.resolve();
+ });
+};
+
+/**
+ * Initialises tag management page.
+ *
+ * @method initManagePage
+ */
+export const initManagePage = () => {
+ // Set cell 'time modified' to 'now' when any of the element is updated in this row.
+ $('body').on('updated', '[data-inplaceeditable]', function(e) {
+ var pendingPromise = new Pending('core/tag:initManagePage');
+
+ getStrings([
+ {
+ key: 'selecttag',
+ component: 'core_tag',
+ },
+ {
+ key: 'now',
+ component: 'core',
+ },
+ ])
+ .then(function(result) {
+ $('label[for="tagselect' + e.ajaxreturn.itemid + '"]').html(result[0]);
+ $(e.target).closest('tr').find('td.col-timemodified').html(result[1]);
+
+ return;
+ })
+ .always(pendingPromise.resolve)
+ .catch(Notification.exception);
+
+ if (e.ajaxreturn.itemtype === 'tagflag') {
+ var row = $(e.target).closest('tr');
+ if (e.ajaxreturn.value === '0') {
+ row.removeClass('table-warning');
+ } else {
+ row.addClass('table-warning');
+ }
+ }
+ });
+
+ // Confirmation for bulk tag combine button.
+ document.addEventListener('click', async(e) => {
+ const tagManagementCombine = e.target.closest('#tag-management-combine');
+ if (tagManagementCombine) {
+ e.preventDefault();
+ handleCombineRequest(tagManagementCombine);
+ }
+
+ if (e.target.closest('a[data-action="addstandardtag"]')) {
+ e.preventDefault();
+ addStandardTags();
+ }
+
+ const bulkActionDeleteButton = e.target.closest('#tag-management-delete');
+ if (bulkActionDeleteButton) {
+ e.preventDefault();
+ deleteSelectedTags(bulkActionDeleteButton.closest('form'));
+ }
+
+ const rowDeleteButton = e.target.closest('.tagdelete');
+ if (rowDeleteButton) {
+ e.preventDefault();
+ deleteSelectedTag(rowDeleteButton);
+ }
+ });
+
+ // When user changes tag name to some name that already exists suggest to combine the tags.
+ $('body').on('updatefailed', '[data-inplaceeditable][data-itemtype=tagname]', async(e) => {
+ var exception = e.exception; // The exception object returned by the callback.
+ var newvalue = e.newvalue; // The value that user tried to udpated the element to.
+ var tagid = $(e.target).attr('data-itemid');
+ if (exception.errorcode !== 'namesalreadybeeingused') {
+ return;
+ }
+ e.preventDefault(); // This will prevent default error dialogue.
+
+ try {
+ await Notification.saveCancelPromise(
+ getString('confirm'),
+ getString('nameuseddocombine', 'tag'),
+ getString('yes'),
+ getString('cancel'),
+ );
+
+ // The Promise will resolve on 'Yes' button, and reject on 'Cancel' button.
+ const redirectTarget = new URL(window.location);
+ redirectTarget.searchParams.set('newname', newvalue);
+ redirectTarget.searchParams.set('tagid', tagid);
+ redirectTarget.searchParams.set('action', 'renamecombine');
+ redirectTarget.searchParams.set('sesskey', Config.sesskey);
+
+ window.location.href = redirectTarget;
+ } catch {
+ return;
+ }
+ });
+};
+
+/**
+ * Initialises tag collection management page.
+ *
+ * @method initManageCollectionsPage
+ */
+export const initManageCollectionsPage = () => {
+ $('body').on('updated', '[data-inplaceeditable]', function(e) {
+ var pendingPromise = new Pending('core/tag:initManageCollectionsPage-updated');
+
+ var ajaxreturn = e.ajaxreturn,
+ areaid, collid, isenabled;
+ if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {
+ areaid = $(this).attr('data-itemid');
+ $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
+ isenabled = ajaxreturn.value;
+ if (isenabled === '1') {
+ $(this).closest('tr').removeClass('dimmed_text');
+ collid = $(this).closest('tr').find('[data-itemtype="tagareacollection"]').attr("data-value");
+ $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
+ } else {
+ $(this).closest('tr').addClass('dimmed_text');
+ }
+ }
+ if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareacollection') {
+ areaid = $(this).attr('data-itemid');
+ $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").hide();
+ collid = $(this).attr('data-value');
+ isenabled = $(this).closest('tr').find('[data-itemtype="tagareaenable"]').attr("data-value");
+ if (isenabled === "1") {
+ $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]").show();
+ }
+ }
+
+ pendingPromise.resolve();
+ });
+
+ document.addEventListener('click', async(e) => {
+ const addTagCollectionNode = e.target.closest('.addtagcoll > a');
+ if (addTagCollectionNode) {
+ e.preventDefault();
+ addTagCollection(addTagCollectionNode);
+ return;
+ }
+
+ const deleteCollectionButton = e.target.closest('.tag-collections-table .action_delete');
+ if (deleteCollectionButton) {
+ e.preventDefault();
+ deleteSelectedCollection(deleteCollectionButton);
+ }
+ });
+};