From 9a75e005ba2a80a98222d401ffa5ed8b0519719d Mon Sep 17 00:00:00 2001 From: user Date: Mon, 23 Dec 2024 12:19:12 +0100 Subject: [PATCH] fixup --- amd/build/catquizTestChooser.min.js | 2 +- amd/build/catquizTestChooser.min.js.map | 2 +- amd/build/managecatcontext.min.js | 2 +- amd/build/managecatcontext.min.js.map | 2 +- amd/build/managecatscale.min.js | 2 +- amd/build/managecatscale.min.js.map | 2 +- amd/build/testitem_model_overrides.min.js | 2 +- amd/build/testitem_model_overrides.min.js.map | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/amd/build/catquizTestChooser.min.js b/amd/build/catquizTestChooser.min.js index a8049ba4f..4943bc979 100644 --- a/amd/build/catquizTestChooser.min.js +++ b/amd/build/catquizTestChooser.min.js @@ -6,6 +6,6 @@ define("local_catquiz/catquizTestChooser",["exports"],(function(_exports){Object * @copyright 2023 Georg Maißer * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const SELECTORS_CATTESTCHOOSER="[data-on-change-action]",SELECTORS_CATTESTSUBMIT='[data-action="submitCatTest"]',SELECTORS_CATSCALESUBMIT='[data-action="submitCatScale"]',SELECTORS_CATSCALESUBMITCONTAINER='[id="fitem_id_submitcatscaleoption"]',SELECTORS_CATTESTCHECKBOXES='input[name^="catquiz_subscalecheckbox"]',SELECTORS_REPORTSCALECHECKBOXES='input[id^="id_catquiz_scalereportcheckbox"]',SELECTORS_NUMBEROFFEEDBACKSSUBMIT='[data-action="submitNumberOfFeedbackOptions"]';function setCardDisabledStatus(element){let reportScale=element.checked,ownId=element.id||element.name,cardBody=element.closest(".card-body");reportScale?cardBody.classList.remove("card-body-disabled"):cardBody.classList.add("card-body-disabled"),[...cardBody.children].filter((c=>!c.id.match(/^accordion/))).forEach((element=>{element.getElementsByTagName("input").forEach((i=>{i.id!=ownId&&(reportScale?i.classList.remove("disabled"):i.classList.add("disabled"))})),element.getElementsByClassName("editor_atto_content").forEach((el=>{el.setAttribute("contenteditable",reportScale)}))}))}function clickNoSubmitButton(element,buttonselector){const form=element.closest("form"),submitCatTest=form.querySelector(buttonselector),fieldset=submitCatTest.closest("fieldset");console.log(submitCatTest,"submitCatTest");const url=new URL(form.action);url.hash=fieldset.id,form.action=url.toString(),submitCatTest.click()}_exports.init=()=>{const selectors=document.querySelectorAll(SELECTORS_CATTESTCHOOSER),checkboxes=document.querySelectorAll(SELECTORS_CATTESTCHECKBOXES),reportscalecheckboxes=document.querySelectorAll(SELECTORS_REPORTSCALECHECKBOXES);var elements=new Set([...selectors,...checkboxes]);if(elements&&0!==elements.length){elements.forEach((selector=>selector.addEventListener("change",(e=>{if(e.target.dataset.manualreload){document.querySelector(SELECTORS_CATSCALESUBMITCONTAINER).classList.remove("hidden");let submitbutton=document.querySelector(SELECTORS_CATSCALESUBMIT);return submitbutton.classList.remove("btn-primary"),submitbutton.classList.add("btn-danger"),void submitbutton.classList.remove("hidden")}switch(e.target.dataset.onChangeAction){case"reloadTestForm":document.getElementsByName("triggered_button")[0].value="reloadTestForm",clickNoSubmitButton(e.target,SELECTORS_CATTESTSUBMIT);break;case"reloadFormFromScaleSelect":clickNoSubmitButton(e.target,SELECTORS_CATSCALESUBMIT);break;case"numberOfFeedbacksSubmit":clickNoSubmitButton(e.target,SELECTORS_NUMBEROFFEEDBACKSSUBMIT)}}))));var checkboxelements=new Set([...reportscalecheckboxes]);checkboxelements&&0!=checkboxelements.length&&checkboxelements.forEach((selector=>{setCardDisabledStatus(selector),selector.addEventListener("change",(e=>setCardDisabledStatus(e.target)))}))}}})); +const SELECTORS_CATTESTCHOOSER="[data-on-change-action]",SELECTORS_CATTESTSUBMIT='[data-action="submitCatTest"]',SELECTORS_CATSCALESUBMIT='[data-action="submitCatScale"]',SELECTORS_CATSCALESUBMITCONTAINER='[id="fitem_id_submitcatscaleoption"]',SELECTORS_CATTESTCHECKBOXES='input[name^="catquiz_subscalecheckbox"]',SELECTORS_REPORTSCALECHECKBOXES='input[id^="id_catquiz_scalereportcheckbox"]',SELECTORS_NUMBEROFFEEDBACKSSUBMIT='[data-action="submitNumberOfFeedbackOptions"]';function setCardDisabledStatus(element){let reportScale=element.checked,ownId=element.id||element.name,cardBody=element.closest(".card-body");reportScale?cardBody.classList.remove("card-body-disabled"):cardBody.classList.add("card-body-disabled"),[...cardBody.children].filter((c=>!c.id.match(/^accordion/))).forEach((element=>{element.getElementsByTagName("input").forEach((i=>{i.id!=ownId&&(reportScale?i.classList.remove("disabled"):i.classList.add("disabled"))})),element.getElementsByClassName("editor_atto_content").forEach((el=>{el.setAttribute("contenteditable",reportScale)}))}))}function clickNoSubmitButton(element,buttonselector){const form=element.closest("form"),submitCatTest=form.querySelector(buttonselector),fieldset=submitCatTest.closest("fieldset");console.log(submitCatTest,"submitCatTest");const url=new URL(form.action);url.hash=fieldset.id,form.action=url.toString(),submitCatTest.click()}_exports.init=()=>{const selectors=document.querySelectorAll(SELECTORS_CATTESTCHOOSER),checkboxes=document.querySelectorAll(SELECTORS_CATTESTCHECKBOXES),reportscalecheckboxes=document.querySelectorAll(SELECTORS_REPORTSCALECHECKBOXES);var elements=new Set([...selectors,...checkboxes]);if(elements&&0!==elements.length){elements.forEach((selector=>selector.addEventListener("change",(e=>{if(e.target.dataset.manualreload){document.querySelector(SELECTORS_CATSCALESUBMITCONTAINER).classList.remove("hidden");let submitbutton=document.querySelector(SELECTORS_CATSCALESUBMIT);return submitbutton.classList.remove("btn-primary"),submitbutton.classList.add("btn-danger"),void submitbutton.classList.remove("hidden")}switch(document.getElementsByName("triggered_button")[0].value="",e.target.dataset.onChangeAction){case"reloadTestForm":document.getElementsByName("triggered_button")[0].value="reloadTestForm",clickNoSubmitButton(e.target,SELECTORS_CATTESTSUBMIT);break;case"reloadFormFromScaleSelect":clickNoSubmitButton(e.target,SELECTORS_CATSCALESUBMIT);break;case"numberOfFeedbacksSubmit":clickNoSubmitButton(e.target,SELECTORS_NUMBEROFFEEDBACKSSUBMIT)}}))));var checkboxelements=new Set([...reportscalecheckboxes]);checkboxelements&&0!=checkboxelements.length&&checkboxelements.forEach((selector=>{setCardDisabledStatus(selector),selector.addEventListener("change",(e=>setCardDisabledStatus(e.target)))}))}}})); //# sourceMappingURL=catquizTestChooser.min.js.map \ No newline at end of file diff --git a/amd/build/catquizTestChooser.min.js.map b/amd/build/catquizTestChooser.min.js.map index c6c8c710e..ca3a8d9e8 100644 --- a/amd/build/catquizTestChooser.min.js.map +++ b/amd/build/catquizTestChooser.min.js.map @@ -1 +1 @@ -{"version":3,"file":"catquizTestChooser.min.js","sources":["../src/catquizTestChooser.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 * JavaScript for mod_form to reload when a CAT model has been chosen.\n *\n * @module mod_adaptivequiz/catquizTestChooser\n * @copyright 2023 Georg Maißer \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst SELECTORS = {\n CATTESTCHOOSER: '[data-on-change-action]',\n CATTESTSUBMIT: '[data-action=\"submitCatTest\"]',\n CATSCALESUBMIT: '[data-action=\"submitCatScale\"]',\n CATSCALESUBMITCONTAINER: '[id=\"fitem_id_submitcatscaleoption\"]',\n CATTESTCHECKBOXES: 'input[name^=\"catquiz_subscalecheckbox\"]',\n REPORTSCALECHECKBOXES: 'input[id^=\"id_catquiz_scalereportcheckbox\"]',\n NUMBEROFFEEDBACKSSUBMIT: '[data-action=\"submitNumberOfFeedbackOptions\"]'\n};\n\n/**\n * Initialise it all.\n */\nexport const init = () => {\n\n const selectors = document.querySelectorAll(SELECTORS.CATTESTCHOOSER);\n const checkboxes = document.querySelectorAll(SELECTORS.CATTESTCHECKBOXES);\n const reportscalecheckboxes = document.querySelectorAll(SELECTORS.REPORTSCALECHECKBOXES);\n\n var elements = new Set([\n ...selectors,\n ...checkboxes\n ]);\n if (!elements) {\n return;\n }\n\n if (elements.length === 0) {\n return;\n }\n elements.forEach(selector =>\n selector.addEventListener('change', e => {\n // Setting defines if reload should be triggered automatically.\n if (e.target.dataset.manualreload) {\n let submitbuttoncontainer = document.querySelector(SELECTORS.CATSCALESUBMITCONTAINER);\n submitbuttoncontainer.classList.remove('hidden');\n\n let submitbutton = document.querySelector(SELECTORS.CATSCALESUBMIT);\n submitbutton.classList.remove('btn-primary');\n submitbutton.classList.add('btn-danger');\n submitbutton.classList.remove('hidden');\n return;\n }\n\n switch (e.target.dataset.onChangeAction) {\n case 'reloadTestForm':\n document.getElementsByName('triggered_button')[0].value = 'reloadTestForm';\n clickNoSubmitButton(e.target, SELECTORS.CATTESTSUBMIT);\n break;\n case 'reloadFormFromScaleSelect':\n clickNoSubmitButton(e.target, SELECTORS.CATSCALESUBMIT);\n break;\n case 'numberOfFeedbacksSubmit':\n clickNoSubmitButton(e.target, SELECTORS.NUMBEROFFEEDBACKSSUBMIT);\n break;\n }\n\n })\n );\n\n // Add a listener to the report checkboxes\n var checkboxelements = new Set([\n ...reportscalecheckboxes\n ]);\n if (!checkboxelements || checkboxelements.length == 0) {\n return;\n }\n\n // On the first run when the page is loaded set the status according to\n // saved fields and add event listeners.\n checkboxelements.forEach(selector => {\n setCardDisabledStatus(selector);\n selector.addEventListener('change', e => setCardDisabledStatus(e.target));\n });\n};\n\n/**\n * Checks the report scale checkbox and disables/enables the input fields accordingly\n *\n * @param {HTMLElement} element\n */\nfunction setCardDisabledStatus(element) {\n let reportScale = element.checked;\n let ownId = element.id || element.name;\n // Get the closest parent.\n let cardBody = element.closest('.card-body');\n if (!reportScale) {\n cardBody.classList.add('card-body-disabled');\n } else {\n cardBody.classList.remove('card-body-disabled');\n }\n // We want to just disable the form fields for the currently selected scale, not the nested scales.\n let currentScaleFields = [...cardBody.children].filter(c => !c.id.match(/^accordion/));\n\n currentScaleFields.forEach(element => {\n // Add or remove a 'disabled' class to all child input elements.\n element\n .getElementsByTagName('input')\n .forEach((i) => {\n if (i.id == ownId) {\n return;\n }\n if (!reportScale) {\n i.classList.add('disabled');\n } else {\n i.classList.remove('disabled');\n }\n });\n\n // Set the 'contenteditable' attribute of the text editor to disable/enable editing.\n element\n .getElementsByClassName('editor_atto_content')\n .forEach((el) => {\n el.setAttribute('contenteditable', reportScale);\n });\n });\n}\n\n/**\n * No Submit Button triggered.\n * @param {HTMLElement} element\n * @param {string} buttonselector\n */\nfunction clickNoSubmitButton(element, buttonselector) {\n\n const form = element.closest('form');\n // Find container for query selector.\n const submitCatTest = form.querySelector(buttonselector);\n const fieldset = submitCatTest.closest('fieldset');\n\n // eslint-disable-next-line no-console\n console.log(submitCatTest, 'submitCatTest');\n\n const url = new URL(form.action);\n url.hash = fieldset.id;\n\n form.action = url.toString();\n submitCatTest.click();\n}\n"],"names":["SELECTORS","setCardDisabledStatus","element","reportScale","checked","ownId","id","name","cardBody","closest","classList","remove","add","children","filter","c","match","forEach","getElementsByTagName","i","getElementsByClassName","el","setAttribute","clickNoSubmitButton","buttonselector","form","submitCatTest","querySelector","fieldset","console","log","url","URL","action","hash","toString","click","selectors","document","querySelectorAll","checkboxes","reportscalecheckboxes","elements","Set","length","selector","addEventListener","e","target","dataset","manualreload","submitbutton","onChangeAction","getElementsByName","value","checkboxelements"],"mappings":";;;;;;;;MAuBMA,yBACc,0BADdA,wBAEa,gCAFbA,yBAGc,iCAHdA,kCAIuB,uCAJvBA,4BAKiB,0CALjBA,gCAMqB,8CANrBA,kCAOuB,yDA0EpBC,sBAAsBC,aACvBC,YAAcD,QAAQE,QACtBC,MAAQH,QAAQI,IAAMJ,QAAQK,KAE9BC,SAAWN,QAAQO,QAAQ,cAC1BN,YAGDK,SAASE,UAAUC,OAAO,sBAF1BH,SAASE,UAAUE,IAAI,sBAKF,IAAIJ,SAASK,UAAUC,QAAOC,IAAMA,EAAET,GAAGU,MAAM,gBAErDC,SAAQf,UAEvBA,QACKgB,qBAAqB,SACrBD,SAASE,IACFA,EAAEb,IAAMD,QAGPF,YAGDgB,EAAET,UAAUC,OAAO,YAFnBQ,EAAET,UAAUE,IAAI,gBAO5BV,QACKkB,uBAAuB,uBACvBH,SAASI,KACNA,GAAGC,aAAa,kBAAmBnB,4BAU1CoB,oBAAoBrB,QAASsB,sBAE5BC,KAAOvB,QAAQO,QAAQ,QAEvBiB,cAAgBD,KAAKE,cAAcH,gBACnCI,SAAWF,cAAcjB,QAAQ,YAGvCoB,QAAQC,IAAIJ,cAAe,uBAErBK,IAAM,IAAIC,IAAIP,KAAKQ,QACzBF,IAAIG,KAAON,SAAStB,GAEpBmB,KAAKQ,OAASF,IAAII,WAClBT,cAAcU,sBA5HE,WAEVC,UAAYC,SAASC,iBAAiBvC,0BACtCwC,WAAaF,SAASC,iBAAiBvC,6BACvCyC,sBAAwBH,SAASC,iBAAiBvC,qCAEpD0C,SAAW,IAAIC,IAAI,IAChBN,aACAG,gBAEFE,UAImB,IAApBA,SAASE,QAGbF,SAASzB,SAAQ4B,UACbA,SAASC,iBAAiB,UAAUC,OAE5BA,EAAEC,OAAOC,QAAQC,aAAc,CACHZ,SAASX,cAAc3B,mCAC7BU,UAAUC,OAAO,cAEnCwC,aAAeb,SAASX,cAAc3B,iCAC1CmD,aAAazC,UAAUC,OAAO,eAC9BwC,aAAazC,UAAUE,IAAI,mBAC3BuC,aAAazC,UAAUC,OAAO,iBAI1BoC,EAAEC,OAAOC,QAAQG,oBAChB,iBACDd,SAASe,kBAAkB,oBAAoB,GAAGC,MAAQ,iBAC1D/B,oBAAoBwB,EAAEC,OAAQhD,mCAE7B,4BACDuB,oBAAoBwB,EAAEC,OAAQhD,oCAE7B,0BACDuB,oBAAoBwB,EAAEC,OAAQhD,6CAQ1CuD,iBAAmB,IAAIZ,IAAI,IACxBF,wBAEFc,kBAA+C,GAA3BA,iBAAiBX,QAM1CW,iBAAiBtC,SAAQ4B,WACrB5C,sBAAsB4C,UACtBA,SAASC,iBAAiB,UAAUC,GAAK9C,sBAAsB8C,EAAEC"} \ No newline at end of file +{"version":3,"file":"catquizTestChooser.min.js","sources":["../src/catquizTestChooser.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 * JavaScript for mod_form to reload when a CAT model has been chosen.\n *\n * @module mod_adaptivequiz/catquizTestChooser\n * @copyright 2023 Georg Maißer \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst SELECTORS = {\n CATTESTCHOOSER: '[data-on-change-action]',\n CATTESTSUBMIT: '[data-action=\"submitCatTest\"]',\n CATSCALESUBMIT: '[data-action=\"submitCatScale\"]',\n CATSCALESUBMITCONTAINER: '[id=\"fitem_id_submitcatscaleoption\"]',\n CATTESTCHECKBOXES: 'input[name^=\"catquiz_subscalecheckbox\"]',\n REPORTSCALECHECKBOXES: 'input[id^=\"id_catquiz_scalereportcheckbox\"]',\n NUMBEROFFEEDBACKSSUBMIT: '[data-action=\"submitNumberOfFeedbackOptions\"]'\n};\n\n/**\n * Initialise it all.\n */\nexport const init = () => {\n\n const selectors = document.querySelectorAll(SELECTORS.CATTESTCHOOSER);\n const checkboxes = document.querySelectorAll(SELECTORS.CATTESTCHECKBOXES);\n const reportscalecheckboxes = document.querySelectorAll(SELECTORS.REPORTSCALECHECKBOXES);\n\n var elements = new Set([\n ...selectors,\n ...checkboxes\n ]);\n if (!elements) {\n return;\n }\n\n if (elements.length === 0) {\n return;\n }\n elements.forEach(selector =>\n selector.addEventListener('change', e => {\n // Setting defines if reload should be triggered automatically.\n if (e.target.dataset.manualreload) {\n let submitbuttoncontainer = document.querySelector(SELECTORS.CATSCALESUBMITCONTAINER);\n submitbuttoncontainer.classList.remove('hidden');\n\n let submitbutton = document.querySelector(SELECTORS.CATSCALESUBMIT);\n submitbutton.classList.remove('btn-primary');\n submitbutton.classList.add('btn-danger');\n submitbutton.classList.remove('hidden');\n return;\n }\n let triggeredButtonField = document.getElementsByName('triggered_button')[0];\n triggeredButtonField.value = '';\n\n switch (e.target.dataset.onChangeAction) {\n case 'reloadTestForm':\n document.getElementsByName('triggered_button')[0].value = 'reloadTestForm';\n clickNoSubmitButton(e.target, SELECTORS.CATTESTSUBMIT);\n break;\n case 'reloadFormFromScaleSelect':\n clickNoSubmitButton(e.target, SELECTORS.CATSCALESUBMIT);\n break;\n case 'numberOfFeedbacksSubmit':\n clickNoSubmitButton(e.target, SELECTORS.NUMBEROFFEEDBACKSSUBMIT);\n break;\n }\n\n })\n );\n\n // Add a listener to the report checkboxes\n var checkboxelements = new Set([\n ...reportscalecheckboxes\n ]);\n if (!checkboxelements || checkboxelements.length == 0) {\n return;\n }\n\n // On the first run when the page is loaded set the status according to\n // saved fields and add event listeners.\n checkboxelements.forEach(selector => {\n setCardDisabledStatus(selector);\n selector.addEventListener('change', e => setCardDisabledStatus(e.target));\n });\n};\n\n/**\n * Checks the report scale checkbox and disables/enables the input fields accordingly\n *\n * @param {HTMLElement} element\n */\nfunction setCardDisabledStatus(element) {\n let reportScale = element.checked;\n let ownId = element.id || element.name;\n // Get the closest parent.\n let cardBody = element.closest('.card-body');\n if (!reportScale) {\n cardBody.classList.add('card-body-disabled');\n } else {\n cardBody.classList.remove('card-body-disabled');\n }\n // We want to just disable the form fields for the currently selected scale, not the nested scales.\n let currentScaleFields = [...cardBody.children].filter(c => !c.id.match(/^accordion/));\n\n currentScaleFields.forEach(element => {\n // Add or remove a 'disabled' class to all child input elements.\n element\n .getElementsByTagName('input')\n .forEach((i) => {\n if (i.id == ownId) {\n return;\n }\n if (!reportScale) {\n i.classList.add('disabled');\n } else {\n i.classList.remove('disabled');\n }\n });\n\n // Set the 'contenteditable' attribute of the text editor to disable/enable editing.\n element\n .getElementsByClassName('editor_atto_content')\n .forEach((el) => {\n el.setAttribute('contenteditable', reportScale);\n });\n });\n}\n\n/**\n * No Submit Button triggered.\n * @param {HTMLElement} element\n * @param {string} buttonselector\n */\nfunction clickNoSubmitButton(element, buttonselector) {\n\n const form = element.closest('form');\n // Find container for query selector.\n const submitCatTest = form.querySelector(buttonselector);\n const fieldset = submitCatTest.closest('fieldset');\n\n // eslint-disable-next-line no-console\n console.log(submitCatTest, 'submitCatTest');\n\n const url = new URL(form.action);\n url.hash = fieldset.id;\n\n form.action = url.toString();\n submitCatTest.click();\n}\n"],"names":["SELECTORS","setCardDisabledStatus","element","reportScale","checked","ownId","id","name","cardBody","closest","classList","remove","add","children","filter","c","match","forEach","getElementsByTagName","i","getElementsByClassName","el","setAttribute","clickNoSubmitButton","buttonselector","form","submitCatTest","querySelector","fieldset","console","log","url","URL","action","hash","toString","click","selectors","document","querySelectorAll","checkboxes","reportscalecheckboxes","elements","Set","length","selector","addEventListener","e","target","dataset","manualreload","submitbutton","getElementsByName","value","onChangeAction","checkboxelements"],"mappings":";;;;;;;;MAuBMA,yBACc,0BADdA,wBAEa,gCAFbA,yBAGc,iCAHdA,kCAIuB,uCAJvBA,4BAKiB,0CALjBA,gCAMqB,8CANrBA,kCAOuB,yDA4EpBC,sBAAsBC,aACvBC,YAAcD,QAAQE,QACtBC,MAAQH,QAAQI,IAAMJ,QAAQK,KAE9BC,SAAWN,QAAQO,QAAQ,cAC1BN,YAGDK,SAASE,UAAUC,OAAO,sBAF1BH,SAASE,UAAUE,IAAI,sBAKF,IAAIJ,SAASK,UAAUC,QAAOC,IAAMA,EAAET,GAAGU,MAAM,gBAErDC,SAAQf,UAEvBA,QACKgB,qBAAqB,SACrBD,SAASE,IACFA,EAAEb,IAAMD,QAGPF,YAGDgB,EAAET,UAAUC,OAAO,YAFnBQ,EAAET,UAAUE,IAAI,gBAO5BV,QACKkB,uBAAuB,uBACvBH,SAASI,KACNA,GAAGC,aAAa,kBAAmBnB,4BAU1CoB,oBAAoBrB,QAASsB,sBAE5BC,KAAOvB,QAAQO,QAAQ,QAEvBiB,cAAgBD,KAAKE,cAAcH,gBACnCI,SAAWF,cAAcjB,QAAQ,YAGvCoB,QAAQC,IAAIJ,cAAe,uBAErBK,IAAM,IAAIC,IAAIP,KAAKQ,QACzBF,IAAIG,KAAON,SAAStB,GAEpBmB,KAAKQ,OAASF,IAAII,WAClBT,cAAcU,sBA9HE,WAEVC,UAAYC,SAASC,iBAAiBvC,0BACtCwC,WAAaF,SAASC,iBAAiBvC,6BACvCyC,sBAAwBH,SAASC,iBAAiBvC,qCAEpD0C,SAAW,IAAIC,IAAI,IAChBN,aACAG,gBAEFE,UAImB,IAApBA,SAASE,QAGbF,SAASzB,SAAQ4B,UACbA,SAASC,iBAAiB,UAAUC,OAE5BA,EAAEC,OAAOC,QAAQC,aAAc,CACHZ,SAASX,cAAc3B,mCAC7BU,UAAUC,OAAO,cAEnCwC,aAAeb,SAASX,cAAc3B,iCAC1CmD,aAAazC,UAAUC,OAAO,eAC9BwC,aAAazC,UAAUE,IAAI,mBAC3BuC,aAAazC,UAAUC,OAAO,iBAGP2B,SAASc,kBAAkB,oBAAoB,GACrDC,MAAQ,GAErBN,EAAEC,OAAOC,QAAQK,oBAChB,iBACDhB,SAASc,kBAAkB,oBAAoB,GAAGC,MAAQ,iBAC1D9B,oBAAoBwB,EAAEC,OAAQhD,mCAE7B,4BACDuB,oBAAoBwB,EAAEC,OAAQhD,oCAE7B,0BACDuB,oBAAoBwB,EAAEC,OAAQhD,6CAQ1CuD,iBAAmB,IAAIZ,IAAI,IACxBF,wBAEFc,kBAA+C,GAA3BA,iBAAiBX,QAM1CW,iBAAiBtC,SAAQ4B,WACrB5C,sBAAsB4C,UACtBA,SAASC,iBAAiB,UAAUC,GAAK9C,sBAAsB8C,EAAEC"} \ No newline at end of file diff --git a/amd/build/managecatcontext.min.js b/amd/build/managecatcontext.min.js index 136adb888..4053ca8ee 100644 --- a/amd/build/managecatcontext.min.js +++ b/amd/build/managecatcontext.min.js @@ -3,6 +3,6 @@ define("local_catquiz/managecatcontext",["exports","core_form/modalform","core/s * @package local_shopping_cart * @copyright Wunderbyte GmbH * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.performDeletion=_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_ajax=_interopRequireDefault(_ajax);const SELECTORS_MANAGECATCONTEXT=".manage-catcontext";_exports.init=()=>{document.querySelectorAll(SELECTORS_MANAGECATCONTEXT).forEach((button=>{button.initialized||(button.initialized=!0,button.addEventListener("click",(e=>{e.preventDefault();const element=e.target;"delete"===element.dataset.action?performDeletion(element):function(button){const action=button.dataset.action;let formclass="local_catquiz\\form\\edit_catcontext",formvalues={id:button.dataset.id??0};if("create"===action)formvalues={parentid:button.dataset.id??0};let modalForm=new _modalform.default({formClass:formclass,args:formvalues,modalConfig:{title:(0,_str.get_string)("managecatcontexts","local_catquiz")},returnFocus:button});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(()=>{window.location.reload()})),modalForm.show()}(element)})))}))};const performDeletion=async element=>{const id=element.closest(".list-group-item").dataset.id;_ajax.default.call([{methodname:"local_catquiz_delete_catcontext",args:{id:id},done:function(res){res.success?window.location.reload():(0,_notifications.showNotification)(res.message,"danger")},fail:ex=>{console.log("ex:"+ex)}}])};_exports.performDeletion=performDeletion})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.performDeletion=_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_ajax=_interopRequireDefault(_ajax);const SELECTORS_MANAGECATCONTEXT=".manage-catcontext";_exports.init=()=>{document.querySelectorAll(SELECTORS_MANAGECATCONTEXT).forEach((button=>{button.initialized||(button.initialized=!0,button.addEventListener("click",(e=>{e.preventDefault();const element=e.target;"delete"===element.dataset.action?performDeletion(element):function(button){var _button$dataset$id,_button$dataset$id2;const action=button.dataset.action;let formclass="local_catquiz\\form\\edit_catcontext",formvalues={id:null!==(_button$dataset$id=button.dataset.id)&&void 0!==_button$dataset$id?_button$dataset$id:0};if("create"===action)formvalues={parentid:null!==(_button$dataset$id2=button.dataset.id)&&void 0!==_button$dataset$id2?_button$dataset$id2:0};let modalForm=new _modalform.default({formClass:formclass,args:formvalues,modalConfig:{title:(0,_str.get_string)("managecatcontexts","local_catquiz")},returnFocus:button});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(()=>{window.location.reload()})),modalForm.show()}(element)})))}))};const performDeletion=async element=>{const id=element.closest(".list-group-item").dataset.id;_ajax.default.call([{methodname:"local_catquiz_delete_catcontext",args:{id:id},done:function(res){res.success?window.location.reload():(0,_notifications.showNotification)(res.message,"danger")},fail:ex=>{console.log("ex:"+ex)}}])};_exports.performDeletion=performDeletion})); //# sourceMappingURL=managecatcontext.min.js.map \ No newline at end of file diff --git a/amd/build/managecatcontext.min.js.map b/amd/build/managecatcontext.min.js.map index 14b117b65..35b684431 100644 --- a/amd/build/managecatcontext.min.js.map +++ b/amd/build/managecatcontext.min.js.map @@ -1 +1 @@ -{"version":3,"file":"managecatcontext.min.js","sources":["../src/managecatcontext.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 * @package local_shopping_cart\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\nimport {showNotification} from 'local_catquiz/notifications';\n\nconst SELECTORS = {\n 'MANAGECATCONTEXT': '.manage-catcontext',\n};\n\n\n/**\n * Add event listener to buttons.\n */\nexport const init = () => {\n let buttons = document.querySelectorAll(SELECTORS.MANAGECATCONTEXT);\n buttons.forEach(button => {\n\n if (button.initialized) {\n return;\n }\n\n button.initialized = true;\n\n button.addEventListener('click', e => {\n e.preventDefault();\n const element = e.target;\n if (element.dataset.action === \"delete\") {\n performDeletion(element);\n } else {\n managecatcontext(element);\n }\n });\n });\n};\n\n/**\n *\n * @param {*} button\n */\nfunction managecatcontext(button) {\n const action = button.dataset.action;\n let formclass = \"local_catquiz\\\\form\\\\edit_catcontext\";\n let formvalues = {\n id: button.dataset.id ?? 0,\n };\n\n switch (action) {\n case 'create':\n formvalues = {parentid: button.dataset.id ?? 0};\n break;\n }\n let modalForm = new ModalForm({\n // Name of the class where form is defined (must extend \\core_form\\dynamic_form):\n formClass: formclass,\n // Add as many arguments as you need, they will be passed to the form:\n args: formvalues,\n // Pass any configuration settings to the modal dialogue, for example, the title:\n modalConfig: {title: getString('managecatcontexts', 'local_catquiz')},\n // DOM element that should get the focus after the modal dialogue is closed:\n returnFocus: button,\n });\n\n // Listen to events if you want to execute something on form submit.\n // Event detail will contain everything the process() function returned:\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, () => {\n\n // Reload window after cancelling.\n window.location.reload();\n });\n\n // Show the form.\n modalForm.show();\n}\n\n/**\n *\n * @param {*} element\n */\nexport const performDeletion = async(element) => {\n\n const parentelement = element.closest('.list-group-item');\n const id = parentelement.dataset.id;\n Ajax.call([{\n methodname: 'local_catquiz_delete_catcontext',\n args: {id: id},\n done: function(res) {\n\n if (res.success) {\n window.location.reload();\n } else {\n showNotification(res.message, 'danger');\n }\n },\n fail: ex => {\n // eslint-disable-next-line no-console\n console.log(\"ex:\" + ex);\n },\n }]);\n};"],"names":["SELECTORS","document","querySelectorAll","forEach","button","initialized","addEventListener","e","preventDefault","element","target","dataset","action","performDeletion","formclass","formvalues","id","parentid","modalForm","ModalForm","formClass","args","modalConfig","title","returnFocus","events","FORM_SUBMITTED","window","location","reload","show","managecatcontext","async","closest","call","methodname","done","res","success","message","fail","ex","console","log"],"mappings":";;;;;mMA0BMA,2BACkB,mCAOJ,KACFC,SAASC,iBAAiBF,4BAChCG,SAAQC,SAERA,OAAOC,cAIXD,OAAOC,aAAc,EAErBD,OAAOE,iBAAiB,SAASC,IAC7BA,EAAEC,uBACIC,QAAUF,EAAEG,OACa,WAA3BD,QAAQE,QAAQC,OAChBC,gBAAgBJ,kBAYNL,cAChBQ,OAASR,OAAOO,QAAQC,WAC1BE,UAAY,uCACZC,WAAa,CACbC,GAAIZ,OAAOO,QAAQK,IAAM,MAIpB,WADDJ,OAEAG,WAAa,CAACE,SAAUb,OAAOO,QAAQK,IAAM,OAGjDE,UAAY,IAAIC,mBAAU,CAE1BC,UAAWN,UAEXO,KAAMN,WAENO,YAAa,CAACC,OAAO,mBAAU,oBAAqB,kBAEpDC,YAAapB,SAKjBc,UAAUZ,iBAAiBY,UAAUO,OAAOC,gBAAgB,KAGxDC,OAAOC,SAASC,YAIpBX,UAAUY,OA1CEC,CAAiBtB,uBAiDpBI,gBAAkBmB,MAAAA,gBAGrBhB,GADgBP,QAAQwB,QAAQ,oBACbtB,QAAQK,iBAC5BkB,KAAK,CAAC,CACPC,WAAY,kCACZd,KAAM,CAACL,GAAIA,IACXoB,KAAM,SAASC,KAEPA,IAAIC,QACJX,OAAOC,SAASC,6CAECQ,IAAIE,QAAS,WAGtCC,KAAMC,KAEFC,QAAQC,IAAI,MAAQF"} \ No newline at end of file +{"version":3,"file":"managecatcontext.min.js","sources":["../src/managecatcontext.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 * @package local_shopping_cart\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\nimport {showNotification} from 'local_catquiz/notifications';\n\nconst SELECTORS = {\n 'MANAGECATCONTEXT': '.manage-catcontext',\n};\n\n\n/**\n * Add event listener to buttons.\n */\nexport const init = () => {\n let buttons = document.querySelectorAll(SELECTORS.MANAGECATCONTEXT);\n buttons.forEach(button => {\n\n if (button.initialized) {\n return;\n }\n\n button.initialized = true;\n\n button.addEventListener('click', e => {\n e.preventDefault();\n const element = e.target;\n if (element.dataset.action === \"delete\") {\n performDeletion(element);\n } else {\n managecatcontext(element);\n }\n });\n });\n};\n\n/**\n *\n * @param {*} button\n */\nfunction managecatcontext(button) {\n const action = button.dataset.action;\n let formclass = \"local_catquiz\\\\form\\\\edit_catcontext\";\n let formvalues = {\n id: button.dataset.id ?? 0,\n };\n\n switch (action) {\n case 'create':\n formvalues = {parentid: button.dataset.id ?? 0};\n break;\n }\n let modalForm = new ModalForm({\n // Name of the class where form is defined (must extend \\core_form\\dynamic_form):\n formClass: formclass,\n // Add as many arguments as you need, they will be passed to the form:\n args: formvalues,\n // Pass any configuration settings to the modal dialogue, for example, the title:\n modalConfig: {title: getString('managecatcontexts', 'local_catquiz')},\n // DOM element that should get the focus after the modal dialogue is closed:\n returnFocus: button,\n });\n\n // Listen to events if you want to execute something on form submit.\n // Event detail will contain everything the process() function returned:\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, () => {\n\n // Reload window after cancelling.\n window.location.reload();\n });\n\n // Show the form.\n modalForm.show();\n}\n\n/**\n *\n * @param {*} element\n */\nexport const performDeletion = async(element) => {\n\n const parentelement = element.closest('.list-group-item');\n const id = parentelement.dataset.id;\n Ajax.call([{\n methodname: 'local_catquiz_delete_catcontext',\n args: {id: id},\n done: function(res) {\n\n if (res.success) {\n window.location.reload();\n } else {\n showNotification(res.message, 'danger');\n }\n },\n fail: ex => {\n // eslint-disable-next-line no-console\n console.log(\"ex:\" + ex);\n },\n }]);\n};"],"names":["SELECTORS","document","querySelectorAll","forEach","button","initialized","addEventListener","e","preventDefault","element","target","dataset","action","performDeletion","formclass","formvalues","id","parentid","modalForm","ModalForm","formClass","args","modalConfig","title","returnFocus","events","FORM_SUBMITTED","window","location","reload","show","managecatcontext","async","closest","call","methodname","done","res","success","message","fail","ex","console","log"],"mappings":";;;;;mMA0BMA,2BACkB,mCAOJ,KACFC,SAASC,iBAAiBF,4BAChCG,SAAQC,SAERA,OAAOC,cAIXD,OAAOC,aAAc,EAErBD,OAAOE,iBAAiB,SAASC,IAC7BA,EAAEC,uBACIC,QAAUF,EAAEG,OACa,WAA3BD,QAAQE,QAAQC,OAChBC,gBAAgBJ,kBAYNL,yDAChBQ,OAASR,OAAOO,QAAQC,WAC1BE,UAAY,uCACZC,WAAa,CACbC,8BAAIZ,OAAOO,QAAQK,oDAAM,MAIpB,WADDJ,OAEAG,WAAa,CAACE,qCAAUb,OAAOO,QAAQK,sDAAM,OAGjDE,UAAY,IAAIC,mBAAU,CAE1BC,UAAWN,UAEXO,KAAMN,WAENO,YAAa,CAACC,OAAO,mBAAU,oBAAqB,kBAEpDC,YAAapB,SAKjBc,UAAUZ,iBAAiBY,UAAUO,OAAOC,gBAAgB,KAGxDC,OAAOC,SAASC,YAIpBX,UAAUY,OA1CEC,CAAiBtB,uBAiDpBI,gBAAkBmB,MAAAA,gBAGrBhB,GADgBP,QAAQwB,QAAQ,oBACbtB,QAAQK,iBAC5BkB,KAAK,CAAC,CACPC,WAAY,kCACZd,KAAM,CAACL,GAAIA,IACXoB,KAAM,SAASC,KAEPA,IAAIC,QACJX,OAAOC,SAASC,6CAECQ,IAAIE,QAAS,WAGtCC,KAAMC,KAEFC,QAAQC,IAAI,MAAQF"} \ No newline at end of file diff --git a/amd/build/managecatscale.min.js b/amd/build/managecatscale.min.js index 89a9f4c9c..7cff55ed8 100644 --- a/amd/build/managecatscale.min.js +++ b/amd/build/managecatscale.min.js @@ -3,6 +3,6 @@ define("local_catquiz/managecatscale",["exports","core_form/modalform","core/str * @package local_shopping_cart * @copyright Wunderbyte GmbH * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.performDeletion=_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_ajax=_interopRequireDefault(_ajax);_exports.init=()=>{document.querySelectorAll(".manage-catscale").forEach((button=>{button.addEventListener("click",(e=>{e.preventDefault();const element=e.target;"delete"===element.dataset.action?performDeletion(element):"view"===element.dataset.action?function(element){let searchParams=new URLSearchParams(window.location.search),scaleid=element.dataset.scaleid,urlscaleid=searchParams.get("scaleid");searchParams.set("scaleid",scaleid);let sdv=0==searchParams.get("sdv")||null===searchParams.get("sdv")||urlscaleid!=scaleid?1:0;searchParams.set("sdv",sdv),window.location.search=searchParams.toString()}(element):function(button){const parentelement=button.closest(".list-group-item"),action=button.dataset.action;let formclass="local_catquiz\\form\\modal_manage_catscale",formvalues={id:parentelement.dataset.id??0,description:parentelement.dataset.description??"",name:parentelement.dataset.name??"",parentid:parentelement.dataset.parentid??0};if("create"===action)formvalues={parentid:parentelement.dataset.id};let modalForm=new _modalform.default({formClass:formclass,args:formvalues,modalConfig:{title:(0,_str.get_string)("managecatscale","local_catquiz")},returnFocus:button});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(e=>{window.console.log(e.detail),window.location.reload()})),modalForm.show()}(element)}))}))};const performDeletion=async element=>{const id=element.closest(".list-group-item").dataset.id;_ajax.default.call([{methodname:"local_catquiz_delete_catscale",args:{id:id},done:function(res){res.success?window.location.reload():(0,_notifications.showNotification)(res.message,"danger")},fail:ex=>{console.log("ex:"+ex)}}])};_exports.performDeletion=performDeletion})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.performDeletion=_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_ajax=_interopRequireDefault(_ajax);_exports.init=()=>{document.querySelectorAll(".manage-catscale").forEach((button=>{button.addEventListener("click",(e=>{e.preventDefault();const element=e.target;"delete"===element.dataset.action?performDeletion(element):"view"===element.dataset.action?function(element){let searchParams=new URLSearchParams(window.location.search),scaleid=element.dataset.scaleid,urlscaleid=searchParams.get("scaleid");searchParams.set("scaleid",scaleid);let sdv=0==searchParams.get("sdv")||null===searchParams.get("sdv")||urlscaleid!=scaleid?1:0;searchParams.set("sdv",sdv),window.location.search=searchParams.toString()}(element):function(button){var _parentelement$datase,_parentelement$datase2,_parentelement$datase3,_parentelement$datase4;const parentelement=button.closest(".list-group-item"),action=button.dataset.action;let formclass="local_catquiz\\form\\modal_manage_catscale",formvalues={id:null!==(_parentelement$datase=parentelement.dataset.id)&&void 0!==_parentelement$datase?_parentelement$datase:0,description:null!==(_parentelement$datase2=parentelement.dataset.description)&&void 0!==_parentelement$datase2?_parentelement$datase2:"",name:null!==(_parentelement$datase3=parentelement.dataset.name)&&void 0!==_parentelement$datase3?_parentelement$datase3:"",parentid:null!==(_parentelement$datase4=parentelement.dataset.parentid)&&void 0!==_parentelement$datase4?_parentelement$datase4:0};if("create"===action)formvalues={parentid:parentelement.dataset.id};let modalForm=new _modalform.default({formClass:formclass,args:formvalues,modalConfig:{title:(0,_str.get_string)("managecatscale","local_catquiz")},returnFocus:button});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(e=>{window.console.log(e.detail),window.location.reload()})),modalForm.show()}(element)}))}))};const performDeletion=async element=>{const id=element.closest(".list-group-item").dataset.id;_ajax.default.call([{methodname:"local_catquiz_delete_catscale",args:{id:id},done:function(res){res.success?window.location.reload():(0,_notifications.showNotification)(res.message,"danger")},fail:ex=>{console.log("ex:"+ex)}}])};_exports.performDeletion=performDeletion})); //# sourceMappingURL=managecatscale.min.js.map \ No newline at end of file diff --git a/amd/build/managecatscale.min.js.map b/amd/build/managecatscale.min.js.map index 07cd67dc8..c861cdc6b 100644 --- a/amd/build/managecatscale.min.js.map +++ b/amd/build/managecatscale.min.js.map @@ -1 +1 @@ -{"version":3,"file":"managecatscale.min.js","sources":["../src/managecatscale.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 * @package local_shopping_cart\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\nimport {showNotification} from 'local_catquiz/notifications';\n\n/**\n * Add event listener to buttons.\n */\nexport const init = () => {\n\n let buttons = document.querySelectorAll('.manage-catscale');\n buttons.forEach(button => {\n button.addEventListener('click', e => {\n e.preventDefault();\n const element = e.target;\n\n if (element.dataset.action === \"delete\") {\n performDeletion(element);\n } else if (element.dataset.action === \"view\") {\n displayDetailView(element);\n } else {\n manageCatscale(element);\n }\n });\n });\n};\n\n/**\n *\n * @param {*} button\n */\nfunction manageCatscale(button) {\n const parentelement = button.closest('.list-group-item');\n const action = button.dataset.action;\n let formclass = \"local_catquiz\\\\form\\\\modal_manage_catscale\";\n let formvalues = {\n id: parentelement.dataset.id ?? 0,\n description: parentelement.dataset.description ?? '',\n name: parentelement.dataset.name ?? '',\n parentid: parentelement.dataset.parentid ?? 0};\n\n switch (action) {\n case 'create':\n formvalues = {parentid: parentelement.dataset.id};\n break;\n }\n let modalForm = new ModalForm({\n // Name of the class where form is defined (must extend \\core_form\\dynamic_form):\n formClass: formclass,\n // Add as many arguments as you need, they will be passed to the form:\n args: formvalues,\n // Pass any configuration settings to the modal dialogue, for example, the title:\n modalConfig: {title: getString('managecatscale', 'local_catquiz')},\n // DOM element that should get the focus after the modal dialogue is closed:\n returnFocus: button,\n });\n\n // Listen to events if you want to execute something on form submit.\n // Event detail will contain everything the process() function returned:\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, (e) => {\n window.console.log(e.detail);\n\n // Reload window after cancelling.\n window.location.reload();\n\n });\n\n // Show the form.\n modalForm.show();\n}\n\n/**\n *\n * @param {*} element\n */\nexport const performDeletion = async(element) => {\n\n const parentelement = element.closest('.list-group-item');\n const id = parentelement.dataset.id;\n Ajax.call([{\n methodname: 'local_catquiz_delete_catscale',\n args: {id: id},\n done: function(res) {\n\n if (res.success) {\n window.location.reload();\n } else {\n showNotification(res.message, 'danger');\n }\n },\n fail: ex => {\n // eslint-disable-next-line no-console\n console.log(\"ex:\" + ex);\n },\n }]);\n};\n\n/**\n *\n * @param {*} element\n */\nfunction displayDetailView(element) {\n\n let searchParams = new URLSearchParams(window.location.search);\n let scaleid = element.dataset.scaleid;\n let urlscaleid = searchParams.get('scaleid');\n searchParams.set('scaleid', scaleid);\n\n // If it's a new scale, we want to display on first click.\n // Otherwise we switch the value.\n let sdv = (searchParams.get('sdv') == 0 || searchParams.get('sdv') === null || urlscaleid != scaleid) ? 1 : 0;\n\n searchParams.set('sdv', sdv);\n window.location.search = searchParams.toString();\n}"],"names":["document","querySelectorAll","forEach","button","addEventListener","e","preventDefault","element","target","dataset","action","performDeletion","searchParams","URLSearchParams","window","location","search","scaleid","urlscaleid","get","set","sdv","toString","displayDetailView","parentelement","closest","formclass","formvalues","id","description","name","parentid","modalForm","ModalForm","formClass","args","modalConfig","title","returnFocus","events","FORM_SUBMITTED","console","log","detail","reload","show","manageCatscale","async","call","methodname","done","res","success","message","fail","ex"],"mappings":";;;;;2MA6BoB,KAEFA,SAASC,iBAAiB,oBAChCC,SAAQC,SACZA,OAAOC,iBAAiB,SAASC,IAC7BA,EAAEC,uBACIC,QAAUF,EAAEG,OAEa,WAA3BD,QAAQE,QAAQC,OAChBC,gBAAgBJ,SACkB,SAA3BA,QAAQE,QAAQC,gBAmFZH,aAEnBK,aAAe,IAAIC,gBAAgBC,OAAOC,SAASC,QACnDC,QAAUV,QAAQE,QAAQQ,QAC1BC,WAAaN,aAAaO,IAAI,WAClCP,aAAaQ,IAAI,UAAWH,aAIxBI,IAAkC,GAA3BT,aAAaO,IAAI,QAA2C,OAA5BP,aAAaO,IAAI,QAAmBD,YAAcD,QAAW,EAAI,EAE5GL,aAAaQ,IAAI,MAAOC,KACxBP,OAAOC,SAASC,OAASJ,aAAaU,WA9F1BC,CAAkBhB,kBAYVJ,cACdqB,cAAgBrB,OAAOsB,QAAQ,oBAC/Bf,OAASP,OAAOM,QAAQC,WAC1BgB,UAAY,6CACZC,WAAa,CACbC,GAAIJ,cAAcf,QAAQmB,IAAM,EAChCC,YAAaL,cAAcf,QAAQoB,aAAe,GAClDC,KAAMN,cAAcf,QAAQqB,MAAQ,GACpCC,SAAUP,cAAcf,QAAQsB,UAAY,MAGvC,WADDrB,OAEAiB,WAAa,CAACI,SAAUP,cAAcf,QAAQmB,QAGlDI,UAAY,IAAIC,mBAAU,CAE1BC,UAAWR,UAEXS,KAAMR,WAENS,YAAa,CAACC,OAAO,mBAAU,iBAAkB,kBAEjDC,YAAanC,SAKjB6B,UAAU5B,iBAAiB4B,UAAUO,OAAOC,gBAAiBnC,IACzDS,OAAO2B,QAAQC,IAAIrC,EAAEsC,QAGrB7B,OAAOC,SAAS6B,YAKpBZ,UAAUa,OA/CEC,CAAevC,sBAsDlBI,gBAAkBoC,MAAAA,gBAGrBnB,GADgBrB,QAAQkB,QAAQ,oBACbhB,QAAQmB,iBAC5BoB,KAAK,CAAC,CACPC,WAAY,gCACZd,KAAM,CAACP,GAAIA,IACXsB,KAAM,SAASC,KAEPA,IAAIC,QACJtC,OAAOC,SAAS6B,6CAECO,IAAIE,QAAS,WAGtCC,KAAMC,KAEFd,QAAQC,IAAI,MAAQa"} \ No newline at end of file +{"version":3,"file":"managecatscale.min.js","sources":["../src/managecatscale.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 * @package local_shopping_cart\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\nimport {showNotification} from 'local_catquiz/notifications';\n\n/**\n * Add event listener to buttons.\n */\nexport const init = () => {\n\n let buttons = document.querySelectorAll('.manage-catscale');\n buttons.forEach(button => {\n button.addEventListener('click', e => {\n e.preventDefault();\n const element = e.target;\n\n if (element.dataset.action === \"delete\") {\n performDeletion(element);\n } else if (element.dataset.action === \"view\") {\n displayDetailView(element);\n } else {\n manageCatscale(element);\n }\n });\n });\n};\n\n/**\n *\n * @param {*} button\n */\nfunction manageCatscale(button) {\n const parentelement = button.closest('.list-group-item');\n const action = button.dataset.action;\n let formclass = \"local_catquiz\\\\form\\\\modal_manage_catscale\";\n let formvalues = {\n id: parentelement.dataset.id ?? 0,\n description: parentelement.dataset.description ?? '',\n name: parentelement.dataset.name ?? '',\n parentid: parentelement.dataset.parentid ?? 0};\n\n switch (action) {\n case 'create':\n formvalues = {parentid: parentelement.dataset.id};\n break;\n }\n let modalForm = new ModalForm({\n // Name of the class where form is defined (must extend \\core_form\\dynamic_form):\n formClass: formclass,\n // Add as many arguments as you need, they will be passed to the form:\n args: formvalues,\n // Pass any configuration settings to the modal dialogue, for example, the title:\n modalConfig: {title: getString('managecatscale', 'local_catquiz')},\n // DOM element that should get the focus after the modal dialogue is closed:\n returnFocus: button,\n });\n\n // Listen to events if you want to execute something on form submit.\n // Event detail will contain everything the process() function returned:\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, (e) => {\n window.console.log(e.detail);\n\n // Reload window after cancelling.\n window.location.reload();\n\n });\n\n // Show the form.\n modalForm.show();\n}\n\n/**\n *\n * @param {*} element\n */\nexport const performDeletion = async(element) => {\n\n const parentelement = element.closest('.list-group-item');\n const id = parentelement.dataset.id;\n Ajax.call([{\n methodname: 'local_catquiz_delete_catscale',\n args: {id: id},\n done: function(res) {\n\n if (res.success) {\n window.location.reload();\n } else {\n showNotification(res.message, 'danger');\n }\n },\n fail: ex => {\n // eslint-disable-next-line no-console\n console.log(\"ex:\" + ex);\n },\n }]);\n};\n\n/**\n *\n * @param {*} element\n */\nfunction displayDetailView(element) {\n\n let searchParams = new URLSearchParams(window.location.search);\n let scaleid = element.dataset.scaleid;\n let urlscaleid = searchParams.get('scaleid');\n searchParams.set('scaleid', scaleid);\n\n // If it's a new scale, we want to display on first click.\n // Otherwise we switch the value.\n let sdv = (searchParams.get('sdv') == 0 || searchParams.get('sdv') === null || urlscaleid != scaleid) ? 1 : 0;\n\n searchParams.set('sdv', sdv);\n window.location.search = searchParams.toString();\n}"],"names":["document","querySelectorAll","forEach","button","addEventListener","e","preventDefault","element","target","dataset","action","performDeletion","searchParams","URLSearchParams","window","location","search","scaleid","urlscaleid","get","set","sdv","toString","displayDetailView","parentelement","closest","formclass","formvalues","id","description","name","parentid","modalForm","ModalForm","formClass","args","modalConfig","title","returnFocus","events","FORM_SUBMITTED","console","log","detail","reload","show","manageCatscale","async","call","methodname","done","res","success","message","fail","ex"],"mappings":";;;;;2MA6BoB,KAEFA,SAASC,iBAAiB,oBAChCC,SAAQC,SACZA,OAAOC,iBAAiB,SAASC,IAC7BA,EAAEC,uBACIC,QAAUF,EAAEG,OAEa,WAA3BD,QAAQE,QAAQC,OAChBC,gBAAgBJ,SACkB,SAA3BA,QAAQE,QAAQC,gBAmFZH,aAEnBK,aAAe,IAAIC,gBAAgBC,OAAOC,SAASC,QACnDC,QAAUV,QAAQE,QAAQQ,QAC1BC,WAAaN,aAAaO,IAAI,WAClCP,aAAaQ,IAAI,UAAWH,aAIxBI,IAAkC,GAA3BT,aAAaO,IAAI,QAA2C,OAA5BP,aAAaO,IAAI,QAAmBD,YAAcD,QAAW,EAAI,EAE5GL,aAAaQ,IAAI,MAAOC,KACxBP,OAAOC,SAASC,OAASJ,aAAaU,WA9F1BC,CAAkBhB,kBAYVJ,6GACdqB,cAAgBrB,OAAOsB,QAAQ,oBAC/Bf,OAASP,OAAOM,QAAQC,WAC1BgB,UAAY,6CACZC,WAAa,CACbC,iCAAIJ,cAAcf,QAAQmB,0DAAM,EAChCC,2CAAaL,cAAcf,QAAQoB,qEAAe,GAClDC,oCAAMN,cAAcf,QAAQqB,8DAAQ,GACpCC,wCAAUP,cAAcf,QAAQsB,kEAAY,MAGvC,WADDrB,OAEAiB,WAAa,CAACI,SAAUP,cAAcf,QAAQmB,QAGlDI,UAAY,IAAIC,mBAAU,CAE1BC,UAAWR,UAEXS,KAAMR,WAENS,YAAa,CAACC,OAAO,mBAAU,iBAAkB,kBAEjDC,YAAanC,SAKjB6B,UAAU5B,iBAAiB4B,UAAUO,OAAOC,gBAAiBnC,IACzDS,OAAO2B,QAAQC,IAAIrC,EAAEsC,QAGrB7B,OAAOC,SAAS6B,YAKpBZ,UAAUa,OA/CEC,CAAevC,sBAsDlBI,gBAAkBoC,MAAAA,gBAGrBnB,GADgBrB,QAAQkB,QAAQ,oBACbhB,QAAQmB,iBAC5BoB,KAAK,CAAC,CACPC,WAAY,gCACZd,KAAM,CAACP,GAAIA,IACXsB,KAAM,SAASC,KAEPA,IAAIC,QACJtC,OAAOC,SAAS6B,6CAECO,IAAIE,QAAS,WAGtCC,KAAMC,KAEFd,QAAQC,IAAI,MAAQa"} \ No newline at end of file diff --git a/amd/build/testitem_model_overrides.min.js b/amd/build/testitem_model_overrides.min.js index e2a3c09b8..89f63db5e 100644 --- a/amd/build/testitem_model_overrides.min.js +++ b/amd/build/testitem_model_overrides.min.js @@ -3,6 +3,6 @@ define("local_catquiz/testitem_model_overrides",["exports","core_form/dynamicfor * @package local_catquiz * @copyright Wunderbyte GmbH * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_dynamicform=(obj=_dynamicform)&&obj.__esModule?obj:{default:obj};const SELECTORS_FORMCONTAINER="#lcq_model_override_form",SELECTORS_NOEDITBUTTON='[name="noedititemparams"]',SELECTORS_MODELSTATUSSELECTS='#lcq_model_override_form .custom-select[name^="override_"]',SELECTORS_ACTIVEMODELSELECT='[name="active_model"]',SELECTORS_TEMP_FIELDS_INPUT='[name="temporaryfields"]',SELECTORS_DELETED_PARAMS_FIELD='[name="deletedparams"]',disabledStates=["0","-5"],syncSelectedState=model=>{const selected=model.value,selectorModel=model.id.match(/id_override_(.*)_select/)[1];let optionUpdateFun=option=>option.removeAttribute("disabled");disabledStates.includes(selected)&&(optionUpdateFun=option=>option.setAttribute("disabled","disabled"));document.querySelector(SELECTORS_ACTIVEMODELSELECT).options.forEach((o=>{o.value!=selectorModel||optionUpdateFun(o)}))},deleteParameters=(model,index)=>{const tempFieldsInput=document.querySelector(SELECTORS_TEMP_FIELDS_INPUT);let tempids=JSON.parse(tempFieldsInput.value),filtered=tempids.filter((newparams=>newparams.model!=model&&newparams.index!=index));if(tempFieldsInput.value=JSON.stringify(filtered),filtered.length!=tempids.length)return;const deletedParamsField=document.querySelector(SELECTORS_DELETED_PARAMS_FIELD);let deletedParams=JSON.parse(deletedParamsField.value);const deleteParam={model:model,index:index};deletedParams.push(deleteParam),deletedParamsField.value=JSON.stringify(deletedParams)};_exports.init=()=>{const dynamicForm=new _dynamicform.default(document.querySelector(SELECTORS_FORMCONTAINER),"local_catquiz\\form\\item_model_override_selector"),switchEditMode=targetModeIsEditing=>{const searchParams=new URLSearchParams(window.location.search);dynamicForm.load({editing:targetModeIsEditing,testitemid:searchParams.get("id"),contextid:searchParams.get("contextid"),scaleid:searchParams.get("scaleid"),component:searchParams.get("component"),updateitem:!0}).then((result=>(document.querySelectorAll(SELECTORS_MODELSTATUSSELECTS).forEach((model=>{syncSelectedState(model),model.addEventListener("change",(e=>syncSelectedState(e.target))),model.addEventListener("change",(e=>(element=>{const model=element.id.match(/id_override_(.*)_select/)[1],disabled=1==element.value;[...document.querySelectorAll(`input[name^="override_${model}["]`),...document.querySelectorAll(`button[data-model="${model}"]`),document.querySelector(`input[value="Add"][data-model="${model}"]`)].forEach((e=>{disabled?e.setAttribute("disabled","disabled"):e.removeAttribute("disabled")}))})(e.target)))})),document.querySelectorAll("#lcq_model_override_form .param-group .align-items-center").forEach((async container=>{const addButton=container.querySelector('[data-action="additemparams"]');if(!addButton)return;const modelName=addButton.getAttribute("data-model")||"",modelFields=addButton.dataset.fields.split(";").map((fd=>fd.split(":")[0]));if(0===modelFields.length)return;const restructured=[];let pairCounter=0;const elements=Array.from(container.children);for(let i=0;icontainer.appendChild(element)))})),result))).catch((err=>err))},addItemParams=e=>{const lastBreak=e.detail.parentElement.parentElement.previousElementSibling,existingInputs=e.detail.closest(".param-group").querySelectorAll('input[type^="fraction_"], input[type^="difficulty_"]'),currentMax=Math.max(...Array.from(existingInputs).map((input=>parseInt(input.getAttribute("type").split("_")[1]||"0")))),newNumber=currentMax+1,pairDiv=document.createElement("div");pairDiv.className="param-pair";const fielddata=e.detail.dataset.fields.split(";");let newIds=[];fielddata.forEach((field=>{const fieldarr=field.split(":"),internalName=fieldarr[0],label=fieldarr[1],newLabel=document.createElement("label");newLabel.textContent=`${label} ${newNumber}`,newLabel.setAttribute("for",`${internalName}_${newNumber}`);const newInput=document.createElement("input");newInput.className="form-control param-input",newInput.id=`${internalName}_${newNumber}`,newInput.setAttribute("type",`${internalName}_${newNumber}`);const wrapper=document.createElement("div");wrapper.className="input-wrapper",wrapper.appendChild(newLabel),wrapper.appendChild(newInput),pairDiv.appendChild(wrapper),newIds.push(newInput.id)}));const deleteBtn=document.createElement("button");deleteBtn.className="btn btn-danger param-delete",deleteBtn.textContent="Delete",deleteBtn.setAttribute("data-param-num",currentMax),deleteBtn.setAttribute("data-param-model",e.detail.dataset.model),deleteBtn.onclick=function(){const model=this.dataset.model,paramNum=this.dataset.paramNum;deleteParameters(model,paramNum),pairDiv.remove()},pairDiv.appendChild(deleteBtn),lastBreak.insertAdjacentElement("afterend",pairDiv);const newBreak=document.createElement("span");newBreak.className="break new-break",pairDiv.insertAdjacentElement("afterend",newBreak);const tempFieldsInput=document.querySelector(SELECTORS_TEMP_FIELDS_INPUT);let tempids=JSON.parse(tempFieldsInput.value);const tempData={model:e.detail.dataset.model,ids:newIds,index:currentMax};tempids.push(tempData),tempFieldsInput.value=JSON.stringify(tempids)};dynamicForm.addEventListener(dynamicForm.events.SUBMIT_BUTTON_PRESSED,(()=>{const tempFieldsInput=document.querySelector(SELECTORS_TEMP_FIELDS_INPUT),newParamData=(addedParamIds=>{let finalData={};return addedParamIds.forEach((newParam=>{const model=newParam.model;finalData[model]=finalData[model]||[];const ids=newParam.ids,params={};ids.forEach((id=>{const value=document.getElementById(id).value;params[id]=value})),finalData[model].push(params)})),finalData})(JSON.parse(tempFieldsInput.value));tempFieldsInput.value=JSON.stringify(newParamData)})),dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED,(e=>{e.preventDefault();let formcontainer=document.querySelector(SELECTORS_FORMCONTAINER);const searchParams=new URLSearchParams(window.location.search);dynamicForm.load({editing:!formcontainer.querySelector(SELECTORS_NOEDITBUTTON),testitemid:searchParams.get("id"),contextid:searchParams.get("contextid"),scaleid:searchParams.get("scaleid"),component:searchParams.get("component"),updateitem:!0}).then((result=>result)).catch((err=>err))})),dynamicForm.addEventListener(dynamicForm.events.NOSUBMIT_BUTTON_PRESSED,(e=>{e.preventDefault();const action=e.detail.dataset.action,targetModeIsEditing="edititemparams"==e.detail.name;switch(action){case"edititemparams":switchEditMode(targetModeIsEditing);break;case"additemparams":addItemParams(e);break;default:console.error(`Unknown no-submit action: ${action}`)}}))}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_dynamicform=(obj=_dynamicform)&&obj.__esModule?obj:{default:obj};const SELECTORS_FORMCONTAINER="#lcq_model_override_form",SELECTORS_NOEDITBUTTON='[name="noedititemparams"]',SELECTORS_MODELSTATUSSELECTS='#lcq_model_override_form .custom-select[name^="override_"]',SELECTORS_ACTIVEMODELSELECT='[name="active_model"]',SELECTORS_TEMP_FIELDS_INPUT='[name="temporaryfields"]',SELECTORS_DELETED_PARAMS_FIELD='[name="deletedparams"]',disabledStates=["0","-5"],syncSelectedState=model=>{const selected=model.value,selectorModel=model.id.match(/id_override_(.*)_select/)[1];let optionUpdateFun=option=>option.removeAttribute("disabled");disabledStates.includes(selected)&&(optionUpdateFun=option=>option.setAttribute("disabled","disabled"));document.querySelector(SELECTORS_ACTIVEMODELSELECT).options.forEach((o=>{o.value!=selectorModel||optionUpdateFun(o)}))},deleteParameters=(model,index)=>{const tempFieldsInput=document.querySelector(SELECTORS_TEMP_FIELDS_INPUT);let tempids=JSON.parse(tempFieldsInput.value),filtered=tempids.filter((newparams=>newparams.model!=model&&newparams.index!=index));if(tempFieldsInput.value=JSON.stringify(filtered),filtered.length!=tempids.length)return;const deletedParamsField=document.querySelector(SELECTORS_DELETED_PARAMS_FIELD);let deletedParams=JSON.parse(deletedParamsField.value);const deleteParam={model:model,index:index};deletedParams.push(deleteParam),deletedParamsField.value=JSON.stringify(deletedParams)};_exports.init=()=>{const dynamicForm=new _dynamicform.default(document.querySelector(SELECTORS_FORMCONTAINER),"local_catquiz\\form\\item_model_override_selector"),switchEditMode=targetModeIsEditing=>{const searchParams=new URLSearchParams(window.location.search);dynamicForm.load({editing:targetModeIsEditing,testitemid:searchParams.get("id"),contextid:searchParams.get("contextid"),scaleid:searchParams.get("scaleid"),component:searchParams.get("component"),updateitem:!0}).then((result=>(document.querySelectorAll(SELECTORS_MODELSTATUSSELECTS).forEach((model=>{syncSelectedState(model),model.addEventListener("change",(e=>syncSelectedState(e.target))),model.addEventListener("change",(e=>(element=>{const model=element.id.match(/id_override_(.*)_select/)[1],disabled=1==element.value;[...document.querySelectorAll('input[name^="override_'.concat(model,'["]')),...document.querySelectorAll('button[data-model="'.concat(model,'"]')),document.querySelector('input[value="Add"][data-model="'.concat(model,'"]'))].forEach((e=>{disabled?e.setAttribute("disabled","disabled"):e.removeAttribute("disabled")}))})(e.target)))})),document.querySelectorAll("#lcq_model_override_form .param-group .align-items-center").forEach((async container=>{const addButton=container.querySelector('[data-action="additemparams"]');if(!addButton)return;const modelName=addButton.getAttribute("data-model")||"",modelFields=addButton.dataset.fields.split(";").map((fd=>fd.split(":")[0]));if(0===modelFields.length)return;const restructured=[];let pairCounter=0;const elements=Array.from(container.children);for(let i=0;icontainer.appendChild(element)))})),result))).catch((err=>err))},addItemParams=e=>{const lastBreak=e.detail.parentElement.parentElement.previousElementSibling,existingInputs=e.detail.closest(".param-group").querySelectorAll('input[type^="fraction_"], input[type^="difficulty_"]'),currentMax=Math.max(...Array.from(existingInputs).map((input=>parseInt(input.getAttribute("type").split("_")[1]||"0")))),newNumber=currentMax+1,pairDiv=document.createElement("div");pairDiv.className="param-pair";const fielddata=e.detail.dataset.fields.split(";");let newIds=[];fielddata.forEach((field=>{const fieldarr=field.split(":"),internalName=fieldarr[0],label=fieldarr[1],newLabel=document.createElement("label");newLabel.textContent="".concat(label," ").concat(newNumber),newLabel.setAttribute("for","".concat(internalName,"_").concat(newNumber));const newInput=document.createElement("input");newInput.className="form-control param-input",newInput.id="".concat(internalName,"_").concat(newNumber),newInput.setAttribute("type","".concat(internalName,"_").concat(newNumber));const wrapper=document.createElement("div");wrapper.className="input-wrapper",wrapper.appendChild(newLabel),wrapper.appendChild(newInput),pairDiv.appendChild(wrapper),newIds.push(newInput.id)}));const deleteBtn=document.createElement("button");deleteBtn.className="btn btn-danger param-delete",deleteBtn.textContent="Delete",deleteBtn.setAttribute("data-param-num",currentMax),deleteBtn.setAttribute("data-param-model",e.detail.dataset.model),deleteBtn.onclick=function(){const model=this.dataset.model,paramNum=this.dataset.paramNum;deleteParameters(model,paramNum),pairDiv.remove()},pairDiv.appendChild(deleteBtn),lastBreak.insertAdjacentElement("afterend",pairDiv);const newBreak=document.createElement("span");newBreak.className="break new-break",pairDiv.insertAdjacentElement("afterend",newBreak);const tempFieldsInput=document.querySelector(SELECTORS_TEMP_FIELDS_INPUT);let tempids=JSON.parse(tempFieldsInput.value);const tempData={model:e.detail.dataset.model,ids:newIds,index:currentMax};tempids.push(tempData),tempFieldsInput.value=JSON.stringify(tempids)};dynamicForm.addEventListener(dynamicForm.events.SUBMIT_BUTTON_PRESSED,(()=>{const tempFieldsInput=document.querySelector(SELECTORS_TEMP_FIELDS_INPUT),newParamData=(addedParamIds=>{let finalData={};return addedParamIds.forEach((newParam=>{const model=newParam.model;finalData[model]=finalData[model]||[];const ids=newParam.ids,params={};ids.forEach((id=>{const value=document.getElementById(id).value;params[id]=value})),finalData[model].push(params)})),finalData})(JSON.parse(tempFieldsInput.value));tempFieldsInput.value=JSON.stringify(newParamData)})),dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED,(e=>{e.preventDefault();let formcontainer=document.querySelector(SELECTORS_FORMCONTAINER);const searchParams=new URLSearchParams(window.location.search);dynamicForm.load({editing:!formcontainer.querySelector(SELECTORS_NOEDITBUTTON),testitemid:searchParams.get("id"),contextid:searchParams.get("contextid"),scaleid:searchParams.get("scaleid"),component:searchParams.get("component"),updateitem:!0}).then((result=>result)).catch((err=>err))})),dynamicForm.addEventListener(dynamicForm.events.NOSUBMIT_BUTTON_PRESSED,(e=>{e.preventDefault();const action=e.detail.dataset.action,targetModeIsEditing="edititemparams"==e.detail.name;switch(action){case"edititemparams":switchEditMode(targetModeIsEditing);break;case"additemparams":addItemParams(e);break;default:console.error("Unknown no-submit action: ".concat(action))}}))}})); //# sourceMappingURL=testitem_model_overrides.min.js.map \ No newline at end of file diff --git a/amd/build/testitem_model_overrides.min.js.map b/amd/build/testitem_model_overrides.min.js.map index dcd54ba51..474ccf3c5 100644 --- a/amd/build/testitem_model_overrides.min.js.map +++ b/amd/build/testitem_model_overrides.min.js.map @@ -1 +1 @@ -{"version":3,"file":"testitem_model_overrides.min.js","sources":["../src/testitem_model_overrides.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 * @package local_catquiz\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DynamicForm from 'core_form/dynamicform';\nimport {get_string as getString} from 'core/str';\n\nconst SELECTORS = {\n FORMCONTAINER: '#lcq_model_override_form',\n NOEDITBUTTON: '[name=\"noedititemparams\"]',\n MODELSTATUSSELECTS: '#lcq_model_override_form .custom-select[name^=\"override_\"]',\n ACTIVEMODELSELECT: '[name=\"active_model\"]',\n TEMP_FIELDS_INPUT: '[name=\"temporaryfields\"]',\n DELETED_PARAMS_FIELD: '[name=\"deletedparams\"]'\n};\n\nconst disabledStates = [\"0\", \"-5\"];\n\n/**\n * Updates the active_model select according to the state of the model status\n *\n * If the state of the model is changed to excluded or not yet calculated, it can not be set as active model.\n * If the state is changed to something else, the disabled attribute is removed.\n *\n * @param {HTMLSelectElement} model\n */\nconst syncSelectedState = (model) => {\n const selected = model.value;\n const selectorModel = model.id.match(/id_override_(.*)_select/)[1];\n let optionUpdateFun = (option) => option.removeAttribute('disabled');\n if (disabledStates.includes(selected)) {\n optionUpdateFun = (option) => option.setAttribute('disabled', 'disabled');\n }\n const activeModelSelect = document.querySelector(SELECTORS.ACTIVEMODELSELECT);\n activeModelSelect.options.forEach((o) => {\n if (o.value == selectorModel) {\n optionUpdateFun(o);\n return;\n }\n });\n};\n\n/**\n * Add values of newly added parameters to a hidden field.\n *\n * When new parameters are added, we store their IDs.\n * This function is called just before we submit the form. It collects the values of those\n * newly added fields and returns them.\n *\n * @param {Array} addedParamIds Array of objects containing model and parameter IDs to be collected.\n * @return {Object} Object containing collected parameter values grouped by model.\n */\nconst collectNewParamData = (addedParamIds) => {\n let finalData = {};\n addedParamIds.forEach(newParam => {\n const model = newParam.model;\n finalData[model] = finalData[model] || [];\n const ids = newParam.ids;\n const params = {};\n ids.forEach(id => {\n const element = document.getElementById(id);\n const value = element.value;\n params[id] = value;\n });\n finalData[model].push(params);\n });\n return finalData;\n};\n\n/**\n * Deletes parameter values for the given model at the given index.\n *\n * If the params were newly added, they are removed from the hidden field that tracks new params.\n * Otherwise, we store information in a hidden field so that the parameters are deleted on the server\n * side once the form is submitted.\n *\n * @param {string} model The model identifier.\n * @param {number} index The index of the parameter set to delete.\n */\nconst deleteParameters = (model, index) => {\n // First, check if this is found in the tempinput data. If so, just remove it from there.\n const tempFieldsInput = document.querySelector(SELECTORS.TEMP_FIELDS_INPUT);\n let tempids = JSON.parse(tempFieldsInput.value);\n let filtered = tempids.filter((newparams) => {\n return newparams.model != model && newparams.index != index;\n });\n tempFieldsInput.value = JSON.stringify(filtered);\n // If the parameter was found, it means we do not have to delete it on the server side.\n // It was temporarily added but not yet saved. So we can return here.\n if (filtered.length != tempids.length) {\n return;\n }\n // If we are here, the parameter should be deleted on the server side.\n const deletedParamsField = document.querySelector(SELECTORS.DELETED_PARAMS_FIELD);\n let deletedParams = JSON.parse(deletedParamsField.value);\n const deleteParam = {\n model: model,\n index: index\n };\n deletedParams.push(deleteParam);\n deletedParamsField.value = JSON.stringify(deletedParams);\n};\n\n/**\n * This adds delete buttons to multiparam models.\n * While at it, it also restructures the HTML a bit by adding some wrapper elements to facilitate styling.\n */\nfunction restructureFormElements() {\n // Find all .align-items-center containers.\n const containers = document.querySelectorAll('#lcq_model_override_form .param-group .align-items-center');\n\n containers.forEach(async container => {\n // Find the Add button and get model data.\n const addButton = container.querySelector('[data-action=\"additemparams\"]');\n if (!addButton) {\n return; // Skip if no add button found.\n }\n\n const modelName = addButton.getAttribute('data-model') || '';\n // Parse field data into array of field names.\n const fielddata = addButton.dataset.fields.split(';');\n const modelFields = fielddata.map(fd => fd.split(':')[0]);\n\n if (modelFields.length === 0) {\n return; // Skip if no fields defined.\n }\n\n // Create new array to store restructured elements.\n const restructured = [];\n let pairCounter = 0;\n const elements = Array.from(container.children);\n\n // Process elements sequentially.\n for (let i = 0; i < elements.length; i++) {\n const currentElement = elements[i];\n\n // Preserve Add button.\n if (currentElement.querySelector('[data-action=\"additemparams\"]')) {\n restructured.push(currentElement.cloneNode(true));\n continue;\n }\n\n // Check if this is the start of an input group (first field's label).\n if (currentElement.tagName === 'LABEL' &&\n elements[i + 1]?.tagName === 'INPUT' &&\n elements[i + 1].getAttribute('type')?.startsWith(`${modelFields[0]}`)) {\n\n // Create wrapper for the parameter group.\n const paramDiv = document.createElement('div');\n paramDiv.className = 'param-pair';\n\n let isValidGroup = true;\n let currentIndex = i;\n\n // Create wrappers for each field in modelFields.\n for (const field of modelFields) {\n const label = elements[currentIndex];\n const input = elements[currentIndex + 1];\n const breakElement = elements[currentIndex + 2];\n\n // Validate the field group.\n if (!label?.tagName === 'LABEL' ||\n !input?.tagName === 'INPUT' ||\n !input?.getAttribute('type')?.startsWith(field)) {\n isValidGroup = false;\n break;\n }\n\n // Create and populate wrapper for this field.\n const wrapper = document.createElement('div');\n wrapper.className = 'input-wrapper';\n wrapper.appendChild(label.cloneNode(true));\n wrapper.appendChild(input.cloneNode(true));\n paramDiv.appendChild(wrapper);\n\n // Move index past current field group.\n currentIndex += breakElement?.classList.contains('break') ? 3 : 2;\n }\n\n if (isValidGroup) {\n // Create delete button.\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'btn btn-danger param-delete';\n deleteBtn.textContent = 'Delete';\n try {\n deleteBtn.textContent = await getString('delete');\n } catch (error) {\n // We already have a fallback, nothing to do here.\n }\n deleteBtn.setAttribute('data-param-num', pairCounter);\n deleteBtn.setAttribute('data-model', modelName);\n deleteBtn.onclick = function() {\n deleteParameters(this.dataset.model, this.dataset.paramNum);\n paramDiv.remove();\n };\n\n paramDiv.appendChild(deleteBtn);\n restructured.push(paramDiv);\n\n // Skip processed elements.\n i = currentIndex - 1;\n pairCounter++;\n }\n } else if (currentElement.classList.contains('break')) {\n // Preserve break elements.\n restructured.push(currentElement.cloneNode(true));\n }\n }\n\n // Clear and repopulate the container.\n container.innerHTML = '';\n restructured.forEach(element => container.appendChild(element));\n });\n}\n\nconst updateModelDisabledStates = (element) => {\n const model = element.id.match(/id_override_(.*)_select/)[1];\n const disabled = element.value == 1;\n // Find the corresponding input fields\n const inputElements = document.querySelectorAll(`input[name^=\"override_${model}[\"]`);\n const deleteButtons = document.querySelectorAll(`button[data-model=\"${model}\"]`);\n const addButton = document.querySelector(`input[value=\"Add\"][data-model=\"${model}\"]`);\n const toUpdate = [...inputElements, ...deleteButtons, addButton];\n toUpdate.forEach(e => {\n if (disabled) {\n e.setAttribute('disabled', 'disabled');\n } else {\n e.removeAttribute('disabled');\n }\n });\n};\n\n/**\n * Add event listener to the form\n */\nexport const init = () => {\n // Initialize the form - pass the container element and the form class name.\n const dynamicForm = new DynamicForm(document.querySelector(\n SELECTORS.FORMCONTAINER),\n 'local_catquiz\\\\form\\\\item_model_override_selector'\n );\n\n const switchEditMode = (targetModeIsEditing) => {\n const searchParams = new URLSearchParams(window.location.search);\n dynamicForm.load({\n editing: targetModeIsEditing,\n testitemid: searchParams.get(\"id\"),\n contextid: searchParams.get(\"contextid\"),\n scaleid: searchParams.get(\"scaleid\"),\n component: searchParams.get(\"component\"),\n updateitem: true\n }).then(\n // Now that the model fields were added, we can add listeners to them.\n (result) => {\n const modelSelectors = document.querySelectorAll(SELECTORS.MODELSTATUSSELECTS);\n modelSelectors.forEach(model => {\n syncSelectedState(model);\n model.addEventListener('change', (e) => syncSelectedState(e.target));\n model.addEventListener('change', e => updateModelDisabledStates(e.target));\n });\n // Add delete buttons etc.\n restructureFormElements();\n return result;\n }\n ).catch(err => err);\n };\n\n const addItemParams = (e) => {\n // Construct the new input fields.\n const lastBreak = e.detail.parentElement.parentElement.previousElementSibling;\n const paramGroup = e.detail.closest('.param-group');\n // Get the current highest number from existing fraction/difficulty inputs\n const existingInputs = paramGroup.querySelectorAll('input[type^=\"fraction_\"], input[type^=\"difficulty_\"]');\n const currentMax = Math.max(...Array.from(existingInputs)\n .map(input => parseInt(input.getAttribute('type').split('_')[1] || '0'))\n );\n const newNumber = currentMax + 1;\n const pairDiv = document.createElement('div');\n pairDiv.className = 'param-pair';\n\n // The fielddata describe the fields to add: \"internalname1:Translated;internalname2:Translated\".\n // For example: \"difficulty:Schwierigkeit;fraction:Fraction\".\n const fielddata = e.detail.dataset.fields.split(';');\n let newIds = [];\n fielddata.forEach(field => {\n const fieldarr = field.split(':');\n const internalName = fieldarr[0];\n const label = fieldarr[1];\n\n const newLabel = document.createElement('label');\n newLabel.textContent = `${label} ${newNumber}`;\n newLabel.setAttribute('for', `${internalName}_${newNumber}`);\n\n const newInput = document.createElement('input');\n newInput.className = 'form-control param-input';\n newInput.id = `${internalName}_${newNumber}`;\n newInput.setAttribute('type', `${internalName}_${newNumber}`);\n\n // Create wrapper.\n const wrapper = document.createElement('div');\n wrapper.className = 'input-wrapper';\n wrapper.appendChild(newLabel);\n wrapper.appendChild(newInput);\n\n pairDiv.appendChild(wrapper);\n newIds.push(newInput.id);\n });\n\n // Create delete button with data attributes\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'btn btn-danger param-delete';\n deleteBtn.textContent = 'Delete';\n deleteBtn.setAttribute('data-param-num', currentMax);\n deleteBtn.setAttribute('data-param-model', e.detail.dataset.model);\n deleteBtn.onclick = function() {\n const model = this.dataset.model;\n const paramNum = this.dataset.paramNum;\n\n deleteParameters(model, paramNum);\n // Remove the input elements.\n pairDiv.remove();\n };\n\n // Assemble the pair\n pairDiv.appendChild(deleteBtn);\n\n lastBreak.insertAdjacentElement('afterend', pairDiv);\n\n const newBreak = document.createElement('span');\n newBreak.className = \"break new-break\";\n pairDiv.insertAdjacentElement('afterend', newBreak);\n\n // Add the IDs of newly added fields to the tempFieldsInput, so that we\n // can collect them easily when the form is submitted.\n const tempFieldsInput = document.querySelector(SELECTORS.TEMP_FIELDS_INPUT);\n let tempids = JSON.parse(tempFieldsInput.value);\n const tempData = {\n model: e.detail.dataset.model,\n ids: newIds,\n index: currentMax, // This is 0-based, so lower than newNumber.\n };\n tempids.push(tempData);\n tempFieldsInput.value = JSON.stringify(tempids);\n };\n\n dynamicForm.addEventListener(dynamicForm.events.SUBMIT_BUTTON_PRESSED, () => {\n const tempFieldsInput = document.querySelector(SELECTORS.TEMP_FIELDS_INPUT);\n const addedParamIds = JSON.parse(tempFieldsInput.value);\n const newParamData = collectNewParamData(addedParamIds);\n tempFieldsInput.value = JSON.stringify(newParamData);\n });\n\n dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED, (e) => {\n e.preventDefault();\n let formcontainer = document.querySelector(\n SELECTORS.FORMCONTAINER);\n const searchParams = new URLSearchParams(window.location.search);\n dynamicForm.load({\n editing: formcontainer.querySelector(SELECTORS.NOEDITBUTTON) ? false : true,\n testitemid: searchParams.get(\"id\"),\n contextid: searchParams.get(\"contextid\"),\n scaleid: searchParams.get(\"scaleid\"),\n component: searchParams.get(\"component\"),\n updateitem: true,\n }).then(result => {\n return result;\n }).catch(err => err);\n });\n\n dynamicForm.addEventListener(dynamicForm.events.NOSUBMIT_BUTTON_PRESSED, (e) => {\n e.preventDefault();\n const action = e.detail.dataset.action;\n const targetModeIsEditing = e.detail.name == 'edititemparams';\n switch (action) {\n case 'edititemparams':\n switchEditMode(targetModeIsEditing);\n break;\n case 'additemparams':\n addItemParams(e);\n break;\n default:\n // eslint-disable-next-line no-console\n console.error(`Unknown no-submit action: ${action}`);\n }\n\n });\n};\n"],"names":["SELECTORS","disabledStates","syncSelectedState","model","selected","value","selectorModel","id","match","optionUpdateFun","option","removeAttribute","includes","setAttribute","document","querySelector","options","forEach","o","deleteParameters","index","tempFieldsInput","tempids","JSON","parse","filtered","filter","newparams","stringify","length","deletedParamsField","deletedParams","deleteParam","push","dynamicForm","DynamicForm","switchEditMode","targetModeIsEditing","searchParams","URLSearchParams","window","location","search","load","editing","testitemid","get","contextid","scaleid","component","updateitem","then","result","querySelectorAll","addEventListener","e","target","element","disabled","updateModelDisabledStates","async","addButton","container","modelName","getAttribute","modelFields","dataset","fields","split","map","fd","restructured","pairCounter","elements","Array","from","children","i","currentElement","cloneNode","tagName","_elements$getAttribut","startsWith","paramDiv","createElement","className","isValidGroup","currentIndex","field","label","input","breakElement","_input$getAttribute","wrapper","appendChild","classList","contains","deleteBtn","textContent","error","onclick","this","paramNum","remove","innerHTML","catch","err","addItemParams","lastBreak","detail","parentElement","previousElementSibling","existingInputs","closest","currentMax","Math","max","parseInt","newNumber","pairDiv","fielddata","newIds","fieldarr","internalName","newLabel","newInput","insertAdjacentElement","newBreak","tempData","ids","events","SUBMIT_BUTTON_PRESSED","newParamData","addedParamIds","finalData","newParam","params","getElementById","collectNewParamData","FORM_SUBMITTED","preventDefault","formcontainer","NOSUBMIT_BUTTON_PRESSED","action","name","console"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"testitem_model_overrides.min.js","sources":["../src/testitem_model_overrides.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 * @package local_catquiz\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DynamicForm from 'core_form/dynamicform';\nimport {get_string as getString} from 'core/str';\n\nconst SELECTORS = {\n FORMCONTAINER: '#lcq_model_override_form',\n NOEDITBUTTON: '[name=\"noedititemparams\"]',\n MODELSTATUSSELECTS: '#lcq_model_override_form .custom-select[name^=\"override_\"]',\n ACTIVEMODELSELECT: '[name=\"active_model\"]',\n TEMP_FIELDS_INPUT: '[name=\"temporaryfields\"]',\n DELETED_PARAMS_FIELD: '[name=\"deletedparams\"]'\n};\n\nconst disabledStates = [\"0\", \"-5\"];\n\n/**\n * Updates the active_model select according to the state of the model status\n *\n * If the state of the model is changed to excluded or not yet calculated, it can not be set as active model.\n * If the state is changed to something else, the disabled attribute is removed.\n *\n * @param {HTMLSelectElement} model\n */\nconst syncSelectedState = (model) => {\n const selected = model.value;\n const selectorModel = model.id.match(/id_override_(.*)_select/)[1];\n let optionUpdateFun = (option) => option.removeAttribute('disabled');\n if (disabledStates.includes(selected)) {\n optionUpdateFun = (option) => option.setAttribute('disabled', 'disabled');\n }\n const activeModelSelect = document.querySelector(SELECTORS.ACTIVEMODELSELECT);\n activeModelSelect.options.forEach((o) => {\n if (o.value == selectorModel) {\n optionUpdateFun(o);\n return;\n }\n });\n};\n\n/**\n * Add values of newly added parameters to a hidden field.\n *\n * When new parameters are added, we store their IDs.\n * This function is called just before we submit the form. It collects the values of those\n * newly added fields and returns them.\n *\n * @param {Array} addedParamIds Array of objects containing model and parameter IDs to be collected.\n * @return {Object} Object containing collected parameter values grouped by model.\n */\nconst collectNewParamData = (addedParamIds) => {\n let finalData = {};\n addedParamIds.forEach(newParam => {\n const model = newParam.model;\n finalData[model] = finalData[model] || [];\n const ids = newParam.ids;\n const params = {};\n ids.forEach(id => {\n const element = document.getElementById(id);\n const value = element.value;\n params[id] = value;\n });\n finalData[model].push(params);\n });\n return finalData;\n};\n\n/**\n * Deletes parameter values for the given model at the given index.\n *\n * If the params were newly added, they are removed from the hidden field that tracks new params.\n * Otherwise, we store information in a hidden field so that the parameters are deleted on the server\n * side once the form is submitted.\n *\n * @param {string} model The model identifier.\n * @param {number} index The index of the parameter set to delete.\n */\nconst deleteParameters = (model, index) => {\n // First, check if this is found in the tempinput data. If so, just remove it from there.\n const tempFieldsInput = document.querySelector(SELECTORS.TEMP_FIELDS_INPUT);\n let tempids = JSON.parse(tempFieldsInput.value);\n let filtered = tempids.filter((newparams) => {\n return newparams.model != model && newparams.index != index;\n });\n tempFieldsInput.value = JSON.stringify(filtered);\n // If the parameter was found, it means we do not have to delete it on the server side.\n // It was temporarily added but not yet saved. So we can return here.\n if (filtered.length != tempids.length) {\n return;\n }\n // If we are here, the parameter should be deleted on the server side.\n const deletedParamsField = document.querySelector(SELECTORS.DELETED_PARAMS_FIELD);\n let deletedParams = JSON.parse(deletedParamsField.value);\n const deleteParam = {\n model: model,\n index: index\n };\n deletedParams.push(deleteParam);\n deletedParamsField.value = JSON.stringify(deletedParams);\n};\n\n/**\n * This adds delete buttons to multiparam models.\n * While at it, it also restructures the HTML a bit by adding some wrapper elements to facilitate styling.\n */\nfunction restructureFormElements() {\n // Find all .align-items-center containers.\n const containers = document.querySelectorAll('#lcq_model_override_form .param-group .align-items-center');\n\n containers.forEach(async container => {\n // Find the Add button and get model data.\n const addButton = container.querySelector('[data-action=\"additemparams\"]');\n if (!addButton) {\n return; // Skip if no add button found.\n }\n\n const modelName = addButton.getAttribute('data-model') || '';\n // Parse field data into array of field names.\n const fielddata = addButton.dataset.fields.split(';');\n const modelFields = fielddata.map(fd => fd.split(':')[0]);\n\n if (modelFields.length === 0) {\n return; // Skip if no fields defined.\n }\n\n // Create new array to store restructured elements.\n const restructured = [];\n let pairCounter = 0;\n const elements = Array.from(container.children);\n\n // Process elements sequentially.\n for (let i = 0; i < elements.length; i++) {\n const currentElement = elements[i];\n\n // Preserve Add button.\n if (currentElement.querySelector('[data-action=\"additemparams\"]')) {\n restructured.push(currentElement.cloneNode(true));\n continue;\n }\n\n // Check if this is the start of an input group (first field's label).\n if (currentElement.tagName === 'LABEL' &&\n elements[i + 1]?.tagName === 'INPUT' &&\n elements[i + 1].getAttribute('type')?.startsWith(`${modelFields[0]}`)) {\n\n // Create wrapper for the parameter group.\n const paramDiv = document.createElement('div');\n paramDiv.className = 'param-pair';\n\n let isValidGroup = true;\n let currentIndex = i;\n\n // Create wrappers for each field in modelFields.\n for (const field of modelFields) {\n const label = elements[currentIndex];\n const input = elements[currentIndex + 1];\n const breakElement = elements[currentIndex + 2];\n\n // Validate the field group.\n if (!label?.tagName === 'LABEL' ||\n !input?.tagName === 'INPUT' ||\n !input?.getAttribute('type')?.startsWith(field)) {\n isValidGroup = false;\n break;\n }\n\n // Create and populate wrapper for this field.\n const wrapper = document.createElement('div');\n wrapper.className = 'input-wrapper';\n wrapper.appendChild(label.cloneNode(true));\n wrapper.appendChild(input.cloneNode(true));\n paramDiv.appendChild(wrapper);\n\n // Move index past current field group.\n currentIndex += breakElement?.classList.contains('break') ? 3 : 2;\n }\n\n if (isValidGroup) {\n // Create delete button.\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'btn btn-danger param-delete';\n deleteBtn.textContent = 'Delete';\n try {\n deleteBtn.textContent = await getString('delete');\n } catch (error) {\n // We already have a fallback, nothing to do here.\n }\n deleteBtn.setAttribute('data-param-num', pairCounter);\n deleteBtn.setAttribute('data-model', modelName);\n deleteBtn.onclick = function() {\n deleteParameters(this.dataset.model, this.dataset.paramNum);\n paramDiv.remove();\n };\n\n paramDiv.appendChild(deleteBtn);\n restructured.push(paramDiv);\n\n // Skip processed elements.\n i = currentIndex - 1;\n pairCounter++;\n }\n } else if (currentElement.classList.contains('break')) {\n // Preserve break elements.\n restructured.push(currentElement.cloneNode(true));\n }\n }\n\n // Clear and repopulate the container.\n container.innerHTML = '';\n restructured.forEach(element => container.appendChild(element));\n });\n}\n\nconst updateModelDisabledStates = (element) => {\n const model = element.id.match(/id_override_(.*)_select/)[1];\n const disabled = element.value == 1;\n // Find the corresponding input fields\n const inputElements = document.querySelectorAll(`input[name^=\"override_${model}[\"]`);\n const deleteButtons = document.querySelectorAll(`button[data-model=\"${model}\"]`);\n const addButton = document.querySelector(`input[value=\"Add\"][data-model=\"${model}\"]`);\n const toUpdate = [...inputElements, ...deleteButtons, addButton];\n toUpdate.forEach(e => {\n if (disabled) {\n e.setAttribute('disabled', 'disabled');\n } else {\n e.removeAttribute('disabled');\n }\n });\n};\n\n/**\n * Add event listener to the form\n */\nexport const init = () => {\n // Initialize the form - pass the container element and the form class name.\n const dynamicForm = new DynamicForm(document.querySelector(\n SELECTORS.FORMCONTAINER),\n 'local_catquiz\\\\form\\\\item_model_override_selector'\n );\n\n const switchEditMode = (targetModeIsEditing) => {\n const searchParams = new URLSearchParams(window.location.search);\n dynamicForm.load({\n editing: targetModeIsEditing,\n testitemid: searchParams.get(\"id\"),\n contextid: searchParams.get(\"contextid\"),\n scaleid: searchParams.get(\"scaleid\"),\n component: searchParams.get(\"component\"),\n updateitem: true\n }).then(\n // Now that the model fields were added, we can add listeners to them.\n (result) => {\n const modelSelectors = document.querySelectorAll(SELECTORS.MODELSTATUSSELECTS);\n modelSelectors.forEach(model => {\n syncSelectedState(model);\n model.addEventListener('change', (e) => syncSelectedState(e.target));\n model.addEventListener('change', e => updateModelDisabledStates(e.target));\n });\n // Add delete buttons etc.\n restructureFormElements();\n return result;\n }\n ).catch(err => err);\n };\n\n const addItemParams = (e) => {\n // Construct the new input fields.\n const lastBreak = e.detail.parentElement.parentElement.previousElementSibling;\n const paramGroup = e.detail.closest('.param-group');\n // Get the current highest number from existing fraction/difficulty inputs\n const existingInputs = paramGroup.querySelectorAll('input[type^=\"fraction_\"], input[type^=\"difficulty_\"]');\n const currentMax = Math.max(...Array.from(existingInputs)\n .map(input => parseInt(input.getAttribute('type').split('_')[1] || '0'))\n );\n const newNumber = currentMax + 1;\n const pairDiv = document.createElement('div');\n pairDiv.className = 'param-pair';\n\n // The fielddata describe the fields to add: \"internalname1:Translated;internalname2:Translated\".\n // For example: \"difficulty:Schwierigkeit;fraction:Fraction\".\n const fielddata = e.detail.dataset.fields.split(';');\n let newIds = [];\n fielddata.forEach(field => {\n const fieldarr = field.split(':');\n const internalName = fieldarr[0];\n const label = fieldarr[1];\n\n const newLabel = document.createElement('label');\n newLabel.textContent = `${label} ${newNumber}`;\n newLabel.setAttribute('for', `${internalName}_${newNumber}`);\n\n const newInput = document.createElement('input');\n newInput.className = 'form-control param-input';\n newInput.id = `${internalName}_${newNumber}`;\n newInput.setAttribute('type', `${internalName}_${newNumber}`);\n\n // Create wrapper.\n const wrapper = document.createElement('div');\n wrapper.className = 'input-wrapper';\n wrapper.appendChild(newLabel);\n wrapper.appendChild(newInput);\n\n pairDiv.appendChild(wrapper);\n newIds.push(newInput.id);\n });\n\n // Create delete button with data attributes\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'btn btn-danger param-delete';\n deleteBtn.textContent = 'Delete';\n deleteBtn.setAttribute('data-param-num', currentMax);\n deleteBtn.setAttribute('data-param-model', e.detail.dataset.model);\n deleteBtn.onclick = function() {\n const model = this.dataset.model;\n const paramNum = this.dataset.paramNum;\n\n deleteParameters(model, paramNum);\n // Remove the input elements.\n pairDiv.remove();\n };\n\n // Assemble the pair\n pairDiv.appendChild(deleteBtn);\n\n lastBreak.insertAdjacentElement('afterend', pairDiv);\n\n const newBreak = document.createElement('span');\n newBreak.className = \"break new-break\";\n pairDiv.insertAdjacentElement('afterend', newBreak);\n\n // Add the IDs of newly added fields to the tempFieldsInput, so that we\n // can collect them easily when the form is submitted.\n const tempFieldsInput = document.querySelector(SELECTORS.TEMP_FIELDS_INPUT);\n let tempids = JSON.parse(tempFieldsInput.value);\n const tempData = {\n model: e.detail.dataset.model,\n ids: newIds,\n index: currentMax, // This is 0-based, so lower than newNumber.\n };\n tempids.push(tempData);\n tempFieldsInput.value = JSON.stringify(tempids);\n };\n\n dynamicForm.addEventListener(dynamicForm.events.SUBMIT_BUTTON_PRESSED, () => {\n const tempFieldsInput = document.querySelector(SELECTORS.TEMP_FIELDS_INPUT);\n const addedParamIds = JSON.parse(tempFieldsInput.value);\n const newParamData = collectNewParamData(addedParamIds);\n tempFieldsInput.value = JSON.stringify(newParamData);\n });\n\n dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED, (e) => {\n e.preventDefault();\n let formcontainer = document.querySelector(\n SELECTORS.FORMCONTAINER);\n const searchParams = new URLSearchParams(window.location.search);\n dynamicForm.load({\n editing: formcontainer.querySelector(SELECTORS.NOEDITBUTTON) ? false : true,\n testitemid: searchParams.get(\"id\"),\n contextid: searchParams.get(\"contextid\"),\n scaleid: searchParams.get(\"scaleid\"),\n component: searchParams.get(\"component\"),\n updateitem: true,\n }).then(result => {\n return result;\n }).catch(err => err);\n });\n\n dynamicForm.addEventListener(dynamicForm.events.NOSUBMIT_BUTTON_PRESSED, (e) => {\n e.preventDefault();\n const action = e.detail.dataset.action;\n const targetModeIsEditing = e.detail.name == 'edititemparams';\n switch (action) {\n case 'edititemparams':\n switchEditMode(targetModeIsEditing);\n break;\n case 'additemparams':\n addItemParams(e);\n break;\n default:\n // eslint-disable-next-line no-console\n console.error(`Unknown no-submit action: ${action}`);\n }\n\n });\n};\n"],"names":["SELECTORS","disabledStates","syncSelectedState","model","selected","value","selectorModel","id","match","optionUpdateFun","option","removeAttribute","includes","setAttribute","document","querySelector","options","forEach","o","deleteParameters","index","tempFieldsInput","tempids","JSON","parse","filtered","filter","newparams","stringify","length","deletedParamsField","deletedParams","deleteParam","push","dynamicForm","DynamicForm","switchEditMode","targetModeIsEditing","searchParams","URLSearchParams","window","location","search","load","editing","testitemid","get","contextid","scaleid","component","updateitem","then","result","querySelectorAll","addEventListener","e","target","element","disabled","updateModelDisabledStates","async","addButton","container","modelName","getAttribute","modelFields","dataset","fields","split","map","fd","restructured","pairCounter","elements","Array","from","children","i","currentElement","cloneNode","tagName","_elements$getAttribut","startsWith","paramDiv","createElement","className","isValidGroup","currentIndex","field","label","input","breakElement","_input$getAttribute","wrapper","appendChild","classList","contains","deleteBtn","textContent","error","onclick","this","paramNum","remove","innerHTML","catch","err","addItemParams","lastBreak","detail","parentElement","previousElementSibling","existingInputs","closest","currentMax","Math","max","parseInt","newNumber","pairDiv","fielddata","newIds","fieldarr","internalName","newLabel","newInput","insertAdjacentElement","newBreak","tempData","ids","events","SUBMIT_BUTTON_PRESSED","newParamData","addedParamIds","finalData","newParam","params","getElementById","collectNewParamData","FORM_SUBMITTED","preventDefault","formcontainer","NOSUBMIT_BUTTON_PRESSED","action","name","console"],"mappings":"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"} \ No newline at end of file