From a7970205248653c8cf4dee9a2ec83355ba87af29 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Fri, 18 Aug 2023 00:01:24 +0800 Subject: [PATCH] MDL-78324 core: Convert core/tag to esm This module is converted to ESM in preparation for simplification of Modal instantiation. --- lib/amd/build/tag.min.js | 16 +- lib/amd/build/tag.min.js.map | 2 +- lib/amd/src/tag.js | 810 +++++++++++++++++------------------ 3 files changed, 405 insertions(+), 423 deletions(-) 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":";;;;;;;;AAuBAA,kBAAO,CACH,SACA,YACA,iBACA,oBACA,WACA,yBACA,oBACA,iBACD,SACCC,EACAC,KACAC,UACAC,aACAC,IACAC,gBACAC,YACAC,eAEqC,CAOjCC,iBAAkB,WAEdR,EAAE,QAAQS,SAAS,wCAAyC,SAAS,SAASC,OACtEC,eAAiB,IAAIJ,QAAQ,6BAEjCG,EAAEE,qBACEC,OAASb,EAAEc,MACXC,MAAQF,OAAO,GAAGG,OAAOC,QAAQ,MAAO,IACxCC,QAAUL,OAAOM,QAAQ,qBACzBC,KAAOL,MAAMM,MAAM,KAAKC,QAAO,SAASC,EAAGC,OACrCC,EAAID,EAAEH,MAAM,YAChBE,EAAEE,EAAE,IAAMC,mBAAmBD,EAAE,IACxBF,IACN,IAEPtB,KAAK0B,KAAK,CAAC,CACPC,WAAY,wBACZR,KAAM,CAACS,SAAUT,SACjB,GACHU,MAAK,SAASC,aACJ7B,UAAU8B,OAAO,iBAAkBD,SAE7CD,MAAK,SAASG,KAAMC,IACjBhC,UAAUiC,YAAYjB,QAASe,KAAMC,OAGxCE,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,eAS5BC,eAAgB,WAEZxC,EAAE,QAAQyC,GAAG,UAAW,0BAA0B,SAAS/B,OACnDC,eAAiB,IAAIJ,QAAQ,8BAEjCH,IAAIsC,YAAY,CACZ,CACIC,IAAK,YACLC,UAAW,YAEf,CACID,IAAK,MACLC,UAAW,UAGlBd,MAAK,SAASe,QACX7C,EAAE,uBAAyBU,EAAEoC,WAAWC,OAAS,MAAMd,KAAKY,OAAO,IACnE7C,EAAEU,EAAEG,QAAQM,QAAQ,MAAM6B,KAAK,uBAAuBf,KAAKY,OAAO,OAIrET,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,WAEU,YAA1B7B,EAAEoC,WAAWG,SAAwB,KACjCC,IAAMlD,EAAEU,EAAEG,QAAQM,QAAQ,MACH,MAAvBT,EAAEoC,WAAWK,MACbD,IAAIE,YAAY,iBAEhBF,IAAIG,SAAS,qBAMzBrD,EAAE,yBAAyBS,SAAS,cAAe,SAAS,SAASC,OAC7DC,eAAiB,IAAIJ,QAAQ,sBAEjCG,EAAEE,qBACE0C,KAAOtD,EAAEc,MAAMyC,KAAK,QACxBnD,IAAIsC,YAAY,CACZ,CAACC,IAAK,SAAUC,UAAW,QAC3B,CAACD,IAAK,mBAAoBC,UAAW,OACrC,CAACD,IAAK,MAAOC,UAAW,QACxB,CAACD,IAAK,KAAMC,UAAW,UAE1Bd,MAAK,SAASP,UACJpB,aAAaqD,QAAQjC,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAAI,WAChDkC,OAAOC,SAASJ,KAAOA,WAG9BlB,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,cAIxBvC,EAAE,0BAA0B2D,OAAM,SAASjD,OACnCkD,KAAO5D,EAAEc,MAAMK,QAAQ,QAAQ0C,IAAI,MAE7B7D,EAAE4D,MAAMZ,KAAK,sEAAsEc,YAKzFnD,eAAiB,IAAIJ,QAAQ,kCAC7BwD,YAAc/D,EAAE,0BAA0BuD,KAAK,OAAQzC,KAAKkD,MAChEtD,EAAEE,iBACFR,IAAIsC,YAAY,CACZ,CAACC,IAAK,SAAUC,UAAW,QAC3B,CAACD,IAAK,oBAAqBC,UAAW,OACtC,CAACD,IAAK,MAAOC,UAAW,QACxB,CAACD,IAAK,KAAMC,UAAW,UAE1Bd,MAAK,SAASP,UACJpB,aAAaqD,QAAQjC,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAAI,WAChDwC,YAAYE,SAASL,MACrBA,KAAKM,eAGZ9B,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,eAIxBvC,EAAE,2BAA2B2D,OAAM,SAASjD,OACpCC,eAAiB,IAAIJ,QAAQ,mCAEjCG,EAAEE,qBACEgD,KAAO5D,EAAEc,MAAMK,QAAQ,QAAQ0C,IAAI,GACnCM,KAAOnE,EAAE4D,MAAMZ,KAAK,yEAEpBmB,KAAKL,QAAU,EACf1D,IAAIsC,YAAY,CACZ,CAACC,IAAK,kBAAmBC,UAAW,OACpC,CAACD,IAAK,qBAAsBC,UAAW,OACvC,CAACD,IAAK,QAETb,MAAK,SAASP,UACJpB,aAAaiE,MAAM7C,EAAE,GAAIA,EAAE,GAAIA,EAAE,OAE3Ca,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,oBAKpBwB,YAAc/D,EAAE,0BAA0BuD,KAAK,OAAQzC,KAAKkD,MAC5DK,eAAiB,GACjBC,WAAa,GACjBH,KAAKI,MAAK,eACFC,MAAQxE,EAAEc,MAAM2D,MAChBC,QAAU1E,EAAE,uDAAyDwE,MAAQ,KAAKjB,KAAK,cAC3Fe,WAAWK,KAAK,CACZC,GAAIJ,MACJR,KAAMU,aAIdtE,IAAIsC,YAAY,CACZ,CAACC,IAAK,kBAAmBC,UAAW,OACpC,CAACD,IAAK,WAAYC,UAAW,UAEhCd,MAAK,SAAS+C,iBACPC,WAAaD,YAAY,GAC7BR,eAAiBQ,YAAY,OACzBE,gBAAkB,CAClBZ,KAAMG,mBAEHjE,gBAAgB2E,OAAO,CAC1BC,MAAOH,WACPI,KAAMhF,UAAU8B,OAAO,wBAAyB+C,iBAChDI,QAAS,CACLC,KAAMf,gBAEVgB,MAAM,EACNC,eAAe,OAGtBxD,MAAK,SAASyD,OAGXA,MAAMC,UAAU/C,GAAGnC,YAAY8E,MAAM,SAAS1E,GAC1CA,EAAEE,iBAGFmD,YAAYE,SAASL,UAEjB6B,QAAUzF,EAAE,8BAA+B,qBAAqByE,MAEpEzE,EAAE,0BAA0BuD,KAAK,OAAQ,WAAWA,KAAK,QAASkC,SAASxB,SAASL,MAEpFA,KAAKM,YAITlE,EAAE,uCAAuC0F,QAAQC,QAAQC,KAAK,WAAW,MAK5ExD,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,eAIxBvC,EAAE,QAAQyC,GAAG,eAAgB,iDAAiD,SAAS/B,OAC/E6B,UAAY7B,EAAE6B,UACdsD,SAAWnF,EAAEmF,SACbrB,MAAQxE,EAAEU,EAAEG,QAAQ0C,KAAK,kBACD,2BAAxBhB,UAAUuD,UAAwC,KAC9CnF,eAAiB,IAAIJ,QAAQ,yBAEjCG,EAAEE,iBACFR,IAAIsC,YAAY,CACZ,CAACC,IAAK,UAAWC,UAAW,QAC5B,CAACD,IAAK,oBAAqBC,UAAW,OACtC,CAACD,IAAK,MAAOC,UAAW,QACxB,CAACD,IAAK,SAAUC,UAAW,UAE9Bd,MAAK,SAASP,UACJpB,aAAaqD,QAAQjC,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAAI,WAChDkC,OAAOC,SAASJ,KAAOG,OAAOC,SAASJ,KAAO,YAAcyC,mBAAmBF,UAC3E,UAAYE,mBAAmBvB,OAC/B,iCAAmCwB,EAAEC,IAAIC,cAGpD9D,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,eAK5BvC,EAAE,QAAQyC,GAAG,QAAS,iCAAiC,SAAS/B,OACxDC,eAAiB,IAAIJ,QAAQ,kCACjCG,EAAEE,iBAEKP,gBAAgB2E,OAAO,CAC1BC,MAAO7E,IAAI+F,WAAW,WAAY,OAClCjB,KAAMhF,UAAU8B,OAAO,oBAAqB,CACxCoE,UAAW3C,OAAOC,SAASJ,KAC3B4C,QAASF,EAAEC,IAAIC,UAEnBf,QAAS,CACLC,KAAMhF,IAAI+F,WAAW,WAAY,SAErCd,MAAM,EACNC,eAAe,IAElBxD,MAAK,SAASyD,OAEXA,MAAMC,UAAU/C,GAAGnC,YAAY8E,MAAM,SAAS1E,OACtC2F,UAAYrG,EAAEU,EAAE4F,eAAetD,KAAK,gBACpCgB,KAAOqC,UAAU5B,MAAM8B,OAG3BF,UAAU5B,IAAIT,UAGVwC,SAAWxG,EAAE,wBACjBwG,SAAS/D,GAAG,UAAU,SAAS/B,OAEvBkD,KAAO5D,EAAE,kBACmB,IAA5B4D,KAAK,GAAG6C,kBACR/F,EAAEE,iBACFF,EAAEgG,mBAEN9C,KAAKP,SAAS,iBAGdrD,EAAE,iCAAiCqD,SAAS,aACxCsD,aAAe3G,EAAE,8BACrB2G,aAAaC,WAAW,UACxBD,aAAatD,SAAS,iBAI1BmD,SAAStC,UAEF,QAMd9B,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,eAS5BsE,0BAA2B,WACvB7G,EAAE,QAAQyC,GAAG,UAAW,0BAA0B,SAAS/B,OAInDoG,OAAQC,OAHRpG,eAAiB,IAAIJ,QAAQ,8CAE7BuC,WAAapC,EAAEoC,WAEU,aAAzBA,WAAWF,WAAoD,kBAAxBE,WAAWG,WAClD6D,OAAS9G,EAAEc,MAAMyC,KAAK,eACtBvD,EAAE,+DAAiE8G,OAAS,KAAKE,OAE/D,MADNlE,WAAWK,OAEnBnD,EAAEc,MAAMK,QAAQ,MAAMiC,YAAY,eAClC2D,OAAS/G,EAAEc,MAAMK,QAAQ,MAAM6B,KAAK,uCAAuCO,KAAK,cAChFvD,EAAE,+CAAiD+G,OAAS,oBAAsBD,OAAS,KAAKzB,QAEhGrF,EAAEc,MAAMK,QAAQ,MAAMkC,SAAS,gBAGV,aAAzBP,WAAWF,WAAoD,sBAAxBE,WAAWG,WAClD6D,OAAS9G,EAAEc,MAAMyC,KAAK,eACtBvD,EAAE,+DAAiE8G,OAAS,KAAKE,OACjFD,OAAS/G,EAAEc,MAAMyC,KAAK,cAEJ,MADNvD,EAAEc,MAAMK,QAAQ,MAAM6B,KAAK,mCAAmCO,KAAK,eAE3EvD,EAAE,+CAAiD+G,OAAS,oBAAsBD,OAAS,KAAKzB,QAIxG1E,eAAe0B,aAGnBrC,EAAE,QAAQyC,GAAG,QAAS,mBAAmB,SAAS/B,OAC1CC,eAAiB,IAAIJ,QAAQ,iDAEjCG,EAAEE,qBAYE0C,KAAOtD,EAAEc,MAAMyC,KAAK,YACpBc,eAAiB,GACrBjE,IAAIsC,YAbO,CACP,CACIC,IAAK,aACLC,UAAW,OAEf,CACID,IAAK,SACLC,UAAW,UAOlBd,MAAK,SAAS+C,iBACPC,WAAaD,YAAY,GAC7BR,eAAiBQ,YAAY,OACzBE,gBAAkB,CAClBqB,UAAW9C,KACX4C,QAASF,EAAEC,IAAIC,gBAEZ7F,gBAAgB2E,OAAO,CAC1BC,MAAOH,WACPI,KAAMhF,UAAU8B,OAAO,8BAA+B+C,iBACtDI,QAAS,CACLC,KAAMf,gBAEVgB,MAAM,EACNC,eAAe,OAGtBxD,MAAK,SAASyD,cAEXA,MAAMC,UAAU/C,GAAGnC,YAAY8E,MAAM,SAAS1E,OACtCuG,gBAAkBjH,EAAEU,EAAE4F,eAAetD,KAAK,oBAC1CgB,KAAOiD,gBAAgBxC,MAAM8B,OAEjCU,gBAAgBxC,IAAIT,UAGhBJ,KAAO5D,EAAE,2BACb4D,KAAKnB,GAAG,UAAU,SAAS/B,IAES,IAA5BkD,KAAK,GAAG6C,kBACR/F,EAAEE,iBACFF,EAAEgG,mBAEN9C,KAAKP,SAAS,iBAGdrD,EAAE,wCAAwCqD,SAAS,aAC/CsD,aAAe3G,EAAE,qCACrB2G,aAAaC,WAAW,UACxBD,aAAatD,SAAS,iBAI1BO,KAAKM,UAEE,KAGJqB,SAGVnD,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC,cAGxBvC,EAAE,QAAQyC,GAAG,QAAS,yCAAyC,SAAS/B,OAChEC,eAAiB,IAAIJ,QAAQ,oDAEjCG,EAAEE,qBACE0C,KAAOtD,EAAEc,MAAMyC,KAAK,YAAc,YAAcyC,EAAEC,IAAIC,QAC1D9F,IAAIsC,YAAY,CACZ,CAACC,IAAK,UACN,CAACA,IAAK,iBAAkBC,UAAW,MAAOsE,MAAOlH,EAAEc,MAAMyC,KAAK,kBAC9D,CAACZ,IAAK,OACN,CAACA,IAAK,QAETb,MAAK,SAASP,UACJpB,aAAaqD,QAAQjC,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAAI,WAChDkC,OAAOC,SAASJ,KAAOA,WAG9BlB,OAAOzB,eAAe0B,SACtBC,MAAMnC,aAAaoC"} \ 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); + } + }); +};